tiny-essentials 1.9.0 → 1.9.2

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.
@@ -2202,6 +2202,15 @@ async function asyncReplace(str, regex, asyncFn) {
2202
2202
  }
2203
2203
 
2204
2204
  ;// ./src/legacy/libs/userLevel.mjs
2205
+ /**
2206
+ * Represents a user object used.
2207
+ *
2208
+ * @typedef {Object} UserEditor
2209
+ * @property {number} exp - Current experience points of the user.
2210
+ * @property {number} level - Current level of the user.
2211
+ * @property {number} totalExp - Total accumulated experience.
2212
+ */
2213
+
2205
2214
  /**
2206
2215
  * Class to manage user level-up logic based on experience points.
2207
2216
  */
@@ -2212,26 +2221,95 @@ class TinyLevelUp {
2212
2221
  * @param {number} expLevel - Base experience needed to level up (per level).
2213
2222
  */
2214
2223
  constructor(giveExp, expLevel) {
2224
+ if (typeof giveExp !== 'number' || Number.isNaN(giveExp))
2225
+ throw new Error('giveExp must be a valid number');
2226
+ if (typeof expLevel !== 'number' || Number.isNaN(expLevel))
2227
+ throw new Error('expLevel must be a valid number');
2215
2228
  this.giveExp = giveExp;
2216
2229
  this.expLevel = expLevel;
2217
2230
  }
2218
2231
 
2219
2232
  /**
2220
- * @typedef {{ exp: number, level: number, totalExp: number }} UserResult
2233
+ * Creates a new user object starting at level 0 with 0 experience.
2234
+ * @returns {UserEditor} A fresh user object.
2235
+ */
2236
+ createUser() {
2237
+ return {
2238
+ exp: 0,
2239
+ level: 1,
2240
+ totalExp: 0,
2241
+ };
2242
+ }
2243
+
2244
+ /**
2245
+ * Validates if the given user object has valid numeric properties.
2246
+ * Throws an error if any property is invalid.
2247
+ *
2248
+ * @param {UserEditor} user - The user object to validate.
2249
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2250
+ */
2251
+ validateUser(user) {
2252
+ if (typeof user.exp !== 'number' || Number.isNaN(user.exp))
2253
+ throw new Error('exp must be a valid number');
2254
+ if (typeof user.level !== 'number' || Number.isNaN(user.level))
2255
+ throw new Error('level must be a valid number');
2256
+ if (user.level < 1) throw new Error('level must be at least 1');
2257
+ if (typeof user.totalExp !== 'number' || Number.isNaN(user.totalExp))
2258
+ throw new Error('totalExp must be a valid number');
2259
+ }
2260
+
2261
+ /**
2262
+ * Checks if the given user object is valid by verifying its numeric properties.
2263
+ *
2264
+ * @param {UserEditor} user - The user object to check.
2265
+ * @returns {boolean} `true` if all properties (exp, level, totalExp) are valid numbers; otherwise `false`.
2221
2266
  */
2267
+ isValidUser(user) {
2268
+ if (typeof user.exp !== 'number' || Number.isNaN(user.exp)) return false;
2269
+ if (typeof user.level !== 'number' || Number.isNaN(user.level)) return false;
2270
+ if (user.level < 1) return false;
2271
+ if (typeof user.totalExp !== 'number' || Number.isNaN(user.totalExp)) return false;
2272
+ return true;
2273
+ }
2222
2274
 
2223
2275
  /**
2224
- * @typedef {{ exp: number, level: number, totalExp: any }} UserEditor
2276
+ * Returns the base experience value used for random experience generation.
2277
+ * Throws an error if the internal giveExp value is not a valid number.
2278
+ *
2279
+ * @returns {number} The base experience value.
2280
+ * @throws {Error} If giveExp is not a valid number.
2225
2281
  */
2282
+ getGiveExpBase() {
2283
+ if (typeof this.giveExp !== 'number' || Number.isNaN(this.giveExp))
2284
+ throw new Error('giveExp must be a valid number');
2285
+ return this.giveExp;
2286
+ }
2287
+
2288
+ /**
2289
+ * Returns the base experience required to level up.
2290
+ * Throws an error if the internal expLevel value is not a valid number.
2291
+ *
2292
+ * @returns {number} The base experience needed per level.
2293
+ * @throws {Error} If expLevel is not a valid number.
2294
+ */
2295
+ getExpLevelBase() {
2296
+ if (typeof this.expLevel !== 'number' || Number.isNaN(this.expLevel))
2297
+ throw new Error('expLevel must be a valid number');
2298
+ return this.expLevel;
2299
+ }
2226
2300
 
2227
2301
  /**
2228
2302
  * Validates and adjusts the user's level based on their current experience.
2229
2303
  * @param {UserEditor} user - The user object containing experience and level properties.
2230
- * @returns {UserResult} The updated user object.
2304
+ * @returns {UserEditor} The updated user object.
2305
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2231
2306
  */
2232
2307
  expValidator(user) {
2308
+ const expLevel = this.getExpLevelBase();
2309
+ this.validateUser(user);
2310
+
2233
2311
  let extraValue = 0;
2234
- const nextLevelExp = this.expLevel * user.level;
2312
+ const nextLevelExp = expLevel * user.level;
2235
2313
 
2236
2314
  // Level Up
2237
2315
  if (user.exp >= nextLevelExp) {
@@ -2246,7 +2324,7 @@ class TinyLevelUp {
2246
2324
  if (user.exp < 1 && user.level > 1) {
2247
2325
  user.level--;
2248
2326
  extraValue = Math.abs(user.exp);
2249
- user.exp = this.expLevel * user.level;
2327
+ user.exp = expLevel * user.level;
2250
2328
 
2251
2329
  if (extraValue > 0) return this.remove(user, extraValue, 'extra');
2252
2330
  }
@@ -2256,12 +2334,14 @@ class TinyLevelUp {
2256
2334
 
2257
2335
  /**
2258
2336
  * Calculates the total experience based on the user's level.
2259
- * @param {{ exp: number, level: number }} user - The user object containing experience and level properties.
2337
+ * @param {UserEditor} user - The user object containing experience and level properties.
2260
2338
  * @returns {number} The total experience of the user.
2339
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2261
2340
  */
2262
2341
  getTotalExp(user) {
2342
+ this.validateUser(user);
2263
2343
  let totalExp = 0;
2264
- for (let p = 1; p <= user.level; p++) totalExp += this.expLevel * p;
2344
+ for (let p = 1; p <= user.level; p++) totalExp += this.getExpLevelBase() * p;
2265
2345
  totalExp += user.exp;
2266
2346
  return totalExp;
2267
2347
  }
@@ -2272,34 +2352,52 @@ class TinyLevelUp {
2272
2352
  * @returns {number} The generated experience points.
2273
2353
  */
2274
2354
  expGenerator(multi = 1) {
2275
- return Math.floor(Math.random() * this.giveExp) + 1 * multi;
2355
+ if (typeof multi !== 'number' || Number.isNaN(multi))
2356
+ throw new Error('multi must be a valid number');
2357
+ return Math.floor(Math.random() * this.getGiveExpBase()) * multi;
2358
+ }
2359
+
2360
+ /**
2361
+ * Calculates how much experience is missing to next level.
2362
+ * @param {UserEditor} user
2363
+ * @returns {number}
2364
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2365
+ */
2366
+ getMissingExp(user) {
2367
+ return this.getProgress(user) - user.exp;
2276
2368
  }
2277
2369
 
2278
2370
  /**
2279
2371
  * Gets the experience points required to reach the next level.
2280
- * @param {{ level: number }} user - The user object containing the level.
2372
+ * @param {UserEditor} user - The user object containing the level.
2281
2373
  * @returns {number} The experience required for the next level.
2374
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2282
2375
  */
2283
2376
  progress(user) {
2284
- return this.expLevel * user.level;
2377
+ return this.getProgress(user);
2285
2378
  }
2286
2379
 
2287
2380
  /**
2288
2381
  * Gets the experience points required to reach the next level.
2289
- * @param {{ level: number }} user - The user object containing the level.
2382
+ * @param {UserEditor} user - The user object containing the level.
2290
2383
  * @returns {number} The experience required for the next level.
2384
+ * @throws {Error} If any property (exp, level, totalExp) is not a valid number.
2291
2385
  */
2292
2386
  getProgress(user) {
2293
- return this.expLevel * user.level;
2387
+ this.validateUser(user);
2388
+ return this.getExpLevelBase() * user.level;
2294
2389
  }
2295
2390
 
2296
2391
  /**
2297
2392
  * Sets the experience value for the user, adjusting their level if necessary.
2298
2393
  * @param {UserEditor} user - The user object.
2299
2394
  * @param {number} value - The new experience value to set.
2300
- * @returns {UserResult} The updated user object.
2395
+ * @returns {UserEditor} The updated user object.
2301
2396
  */
2302
2397
  set(user, value) {
2398
+ if (typeof value !== 'number' || Number.isNaN(value))
2399
+ throw new Error('value must be a valid number');
2400
+
2303
2401
  user.exp = value;
2304
2402
  this.expValidator(user);
2305
2403
  user.totalExp = this.getTotalExp(user);
@@ -2312,9 +2410,15 @@ class TinyLevelUp {
2312
2410
  * @param {number} [extraExp] - Additional experience to be added.
2313
2411
  * @param {'add' | 'extra'} [type] - Type of addition ('add' or 'extra').
2314
2412
  * @param {number} [multi] - Multiplier for experience generation.
2315
- * @returns {UserResult} The updated user object.
2413
+ * @returns {UserEditor} The updated user object.
2316
2414
  */
2317
2415
  give(user, extraExp = 0, type = 'add', multi = 1) {
2416
+ if (typeof multi !== 'number' || Number.isNaN(multi))
2417
+ throw new Error('multi must be a valid number');
2418
+ if (typeof extraExp !== 'number' || Number.isNaN(extraExp))
2419
+ throw new Error('extraExp must be a valid number');
2420
+ if (typeof type !== 'string') throw new Error('type must be a valid string');
2421
+
2318
2422
  if (type === 'add') user.exp += this.expGenerator(multi) + extraExp;
2319
2423
  else if (type === 'extra') user.exp += extraExp;
2320
2424
 
@@ -2329,9 +2433,15 @@ class TinyLevelUp {
2329
2433
  * @param {number} [extraExp] - Additional experience to remove.
2330
2434
  * @param {'add' | 'extra'} [type] - Type of removal ('add' or 'extra').
2331
2435
  * @param {number} [multi] - Multiplier for experience generation.
2332
- * @returns {UserResult} The updated user object.
2436
+ * @returns {UserEditor} The updated user object.
2333
2437
  */
2334
2438
  remove(user, extraExp = 0, type = 'add', multi = 1) {
2439
+ if (typeof multi !== 'number' || Number.isNaN(multi))
2440
+ throw new Error('multi must be a valid number');
2441
+ if (typeof extraExp !== 'number' || Number.isNaN(extraExp))
2442
+ throw new Error('extraExp must be a valid number');
2443
+ if (typeof type !== 'string') throw new Error('type must be a valid string');
2444
+
2335
2445
  if (type === 'add') user.exp -= this.expGenerator(multi) + extraExp;
2336
2446
  else if (type === 'extra') user.exp -= extraExp;
2337
2447
 
@@ -2617,6 +2727,8 @@ var buffer = __webpack_require__(287);
2617
2727
  ;// ./src/v1/basics/objFilter.mjs
2618
2728
 
2619
2729
 
2730
+ const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
2731
+
2620
2732
  /**
2621
2733
  * An object containing type validation functions and their evaluation order.
2622
2734
  *
@@ -2626,111 +2738,27 @@ var buffer = __webpack_require__(287);
2626
2738
  * The `order` array defines the priority in which types should be checked,
2627
2739
  * which can be useful for functions that infer types in a consistent manner.
2628
2740
  *
2629
- * @typedef {Object} TypeValidator
2630
- * @property {Object.<string, (val: any) => boolean>} items - A dictionary of type validation functions.
2631
- * @property {string[]} order - The order in which types should be evaluated.
2632
- */
2633
-
2634
- /**
2635
- * Validates values against specific types using predefined functions.
2636
- *
2637
- * @type {TypeValidator}
2638
2741
  */
2639
2742
  const typeValidator = {
2640
- items: {
2641
- /** @param {*} val @returns {val is undefined} */
2642
- undefined: (val) => typeof val === 'undefined',
2643
-
2644
- /** @param {*} val @returns {val is null} */
2645
- null: (val) => val === null,
2646
-
2647
- /** @param {*} val @returns {val is boolean} */
2648
- boolean: (val) => typeof val === 'boolean',
2649
-
2650
- /** @param {*} val @returns {val is number} */
2651
- number: (val) => typeof val === 'number' && !isNaN(val),
2652
-
2653
- /** @param {*} val @returns {val is bigint} */
2654
- bigint: (val) => typeof val === 'bigint',
2655
-
2656
- /** @param {*} val @returns {val is string} */
2657
- string: (val) => typeof val === 'string',
2658
-
2659
- /** @param {*} val @returns {val is symbol} */
2660
- symbol: (val) => typeof val === 'symbol',
2661
-
2662
- /** @param {*} val @returns {val is Function} */
2663
- function: (val) => typeof val === 'function',
2664
-
2665
- /** @param {*} val @returns {val is Array} */
2666
- array: (val) => Array.isArray(val),
2667
-
2668
- /** @param {*} val @returns {val is Date} */
2669
- date: (val) => val instanceof Date,
2670
-
2671
- /** @param {*} val @returns {val is RegExp} */
2672
- regexp: (val) => val instanceof RegExp,
2673
-
2674
- /** @param {*} val @returns {val is Map} */
2675
- map: (val) => val instanceof Map,
2676
-
2677
- /** @param {*} val @returns {val is Set} */
2678
- set: (val) => val instanceof Set,
2679
-
2680
- /** @param {*} val @returns {val is WeakMap} */
2681
- weakmap: (val) => val instanceof WeakMap,
2682
-
2683
- /** @param {*} val @returns {val is WeakSet} */
2684
- weakset: (val) => val instanceof WeakSet,
2685
-
2686
- /** @param {*} val @returns {val is Promise} */
2687
- promise: (val) => val instanceof Promise,
2688
-
2689
- /** @param {*} val @returns {val is Buffer} */
2690
- buffer: (val) => typeof buffer/* Buffer */.hp !== 'undefined' && buffer/* Buffer */.hp.isBuffer(val),
2691
-
2692
- /** @param {*} val @returns {val is File} */
2693
- file: (val) => typeof File !== 'undefined' && val instanceof File,
2694
-
2695
- /** @param {*} val @returns {val is HTMLElement} */
2696
- htmlelement: (val) => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement,
2697
-
2698
- /** @param {*} val @returns {val is object} */
2699
- object: (val) => typeof val === 'object' && val !== null && !Array.isArray(val),
2700
- },
2701
-
2702
- /** Evaluation order of the type checkers. */
2703
- order: [
2704
- 'undefined',
2705
- 'null',
2706
- 'boolean',
2707
- 'number',
2708
- 'bigint',
2709
- 'string',
2710
- 'symbol',
2711
- 'function',
2712
- 'array',
2713
- 'buffer',
2714
- 'file',
2715
- 'date',
2716
- 'regexp',
2717
- 'map',
2718
- 'set',
2719
- 'weakmap',
2720
- 'weakset',
2721
- 'promise',
2722
- 'htmlelement',
2723
- 'object',
2724
- ],
2743
+ items: {},
2744
+ /**
2745
+ * Evaluation order of the type checkers.
2746
+ * @type {string[]}
2747
+ * */
2748
+ order: [],
2725
2749
  };
2726
2750
 
2751
+ /** @typedef {Object.<string, (val: any) => *>} ExtendObjType */
2752
+ /** @typedef {Array<[string, (val: any) => *]>} ExtendObjTypeArray */
2753
+
2727
2754
  /**
2728
2755
  * Adds new type checkers to the typeValidator without overwriting existing ones.
2729
2756
  *
2730
- * Optionally, you can specify the index at which the new type should be inserted in the order.
2757
+ * Accepts either an object with named functions or an array of [key, fn] arrays.
2731
2758
  * If no index is provided, the type is inserted just before 'object' (if it exists), or at the end.
2732
2759
  *
2733
- * @param {Object.<string, (val: any) => boolean>} newItems - New type validators to be added.
2760
+ * @param {ExtendObjType|ExtendObjTypeArray} newItems
2761
+ * - New type validators to be added.
2734
2762
  * @param {number} [index] - Optional. Position at which to insert each new type. Ignored if the type already exists.
2735
2763
  * @returns {string[]} - A list of successfully added type names.
2736
2764
  *
@@ -2738,12 +2766,20 @@ const typeValidator = {
2738
2766
  * extendObjType({
2739
2767
  * htmlElement2: val => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement
2740
2768
  * });
2769
+ *
2770
+ * @example
2771
+ * extendObjType([
2772
+ * ['alpha', val => typeof val === 'string'],
2773
+ * ['beta', val => Array.isArray(val)]
2774
+ * ]);
2741
2775
  */
2742
2776
  function extendObjType(newItems, index) {
2743
2777
  const added = [];
2744
2778
 
2745
- for (const [key, fn] of Object.entries(newItems)) {
2779
+ const entries = Array.isArray(newItems) ? newItems : Object.entries(newItems);
2780
+ for (const [key, fn] of entries) {
2746
2781
  if (!typeValidator.items.hasOwnProperty(key)) {
2782
+ // @ts-ignore
2747
2783
  typeValidator.items[key] = fn;
2748
2784
 
2749
2785
  let insertAt = typeof index === 'number' ? index : -1; // Default to -1 if index isn't provided
@@ -2821,9 +2857,12 @@ function cloneObjTypeOrder() {
2821
2857
  */
2822
2858
  const getType = (val) => {
2823
2859
  if (val === null) return 'null';
2824
- for (const name of typeValidator.order)
2860
+ // @ts-ignore
2861
+ for (const name of typeValidator.order) {
2862
+ // @ts-ignore
2825
2863
  if (typeof typeValidator.items[name] !== 'function' || typeValidator.items[name](val))
2826
2864
  return name;
2865
+ }
2827
2866
  return 'unknown';
2828
2867
  };
2829
2868
 
@@ -2858,7 +2897,9 @@ function checkObj(obj) {
2858
2897
  /** @type {{ valid:*; type: string | null }} */
2859
2898
  const data = { valid: null, type: null };
2860
2899
  for (const name of typeValidator.order) {
2900
+ // @ts-ignore
2861
2901
  if (typeof typeValidator.items[name] === 'function') {
2902
+ // @ts-ignore
2862
2903
  const result = typeValidator.items[name](obj);
2863
2904
  if (result) {
2864
2905
  data.valid = result;
@@ -2898,6 +2939,132 @@ function countObj(obj) {
2898
2939
  return 0;
2899
2940
  }
2900
2941
 
2942
+ // Insert obj types
2943
+
2944
+ extendObjType([
2945
+ [
2946
+ 'undefined',
2947
+ /** @param {*} val @returns {val is undefined} */
2948
+ (val) => typeof val === 'undefined',
2949
+ ],
2950
+ [
2951
+ 'null',
2952
+ /** @param {*} val @returns {val is null} */
2953
+ (val) => val === null,
2954
+ ],
2955
+ [
2956
+ 'boolean',
2957
+ /** @param {*} val @returns {val is boolean} */
2958
+ (val) => typeof val === 'boolean',
2959
+ ],
2960
+ [
2961
+ 'number',
2962
+ /** @param {*} val @returns {val is number} */
2963
+ (val) => typeof val === 'number' && !Number.isNaN(val),
2964
+ ],
2965
+ [
2966
+ 'bigint',
2967
+ /** @param {*} val @returns {val is bigint} */
2968
+ (val) => typeof val === 'bigint',
2969
+ ],
2970
+ [
2971
+ 'string',
2972
+ /** @param {*} val @returns {val is string} */
2973
+ (val) => typeof val === 'string',
2974
+ ],
2975
+ [
2976
+ 'symbol',
2977
+ /** @param {*} val @returns {val is symbol} */
2978
+ (val) => typeof val === 'symbol',
2979
+ ],
2980
+ [
2981
+ 'function',
2982
+ /** @param {*} val @returns {val is Function} */
2983
+ (val) => typeof val === 'function',
2984
+ ],
2985
+ [
2986
+ 'array',
2987
+ /** @param {*} val @returns {val is any[]} */
2988
+ (val) => Array.isArray(val),
2989
+ ],
2990
+ ]);
2991
+
2992
+ if (!isBrowser) {
2993
+ extendObjType([
2994
+ [
2995
+ 'buffer',
2996
+ /** @param {*} val @returns {val is Buffer} */
2997
+ (val) => typeof buffer/* Buffer */.hp !== 'undefined' && buffer/* Buffer */.hp.isBuffer(val),
2998
+ ],
2999
+ ]);
3000
+ }
3001
+
3002
+ if (isBrowser) {
3003
+ extendObjType([
3004
+ [
3005
+ 'file',
3006
+ /** @param {*} val @returns {val is File} */
3007
+ (val) => typeof File !== 'undefined' && val instanceof File,
3008
+ ],
3009
+ ]);
3010
+ }
3011
+
3012
+ extendObjType([
3013
+ [
3014
+ 'date',
3015
+ /** @param {*} val @returns {val is Date} */
3016
+ (val) => val instanceof Date,
3017
+ ],
3018
+ [
3019
+ 'regexp',
3020
+ /** @param {*} val @returns {val is RegExp} */
3021
+ (val) => val instanceof RegExp,
3022
+ ],
3023
+ [
3024
+ 'map',
3025
+ /** @param {*} val @returns {val is Map<any, any>} */
3026
+ (val) => val instanceof Map,
3027
+ ],
3028
+ [
3029
+ 'set',
3030
+ /** @param {*} val @returns {val is Set<any>} */
3031
+ (val) => val instanceof Set,
3032
+ ],
3033
+ [
3034
+ 'weakmap',
3035
+ /** @param {*} val @returns {val is WeakMap<any, any>} */
3036
+ (val) => val instanceof WeakMap,
3037
+ ],
3038
+ [
3039
+ 'weakset',
3040
+ /** @param {*} val @returns {val is WeakSet<any>} */
3041
+ (val) => val instanceof WeakSet,
3042
+ ],
3043
+ [
3044
+ 'promise',
3045
+ /** @param {*} val @returns {val is Promise<any>} */
3046
+ (val) => val instanceof Promise,
3047
+ ],
3048
+ ]);
3049
+
3050
+ if (isBrowser) {
3051
+ extendObjType([
3052
+ [
3053
+ 'htmlelement',
3054
+ /** @param {*} val @returns {val is HTMLElement} */
3055
+ (val) => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement,
3056
+ ],
3057
+ ]);
3058
+ }
3059
+
3060
+ extendObjType([
3061
+ [
3062
+ 'object',
3063
+ /** @param {*} val @returns {val is object} */
3064
+ (val) => typeof val === 'object' && val !== null && !Array.isArray(val),
3065
+ ],
3066
+ ]);
3067
+
2901
3068
  ;// ./src/v1/basics/simpleMath.mjs
2902
3069
  /**
2903
3070
  * Executes a Rule of Three calculation.
@@ -3311,6 +3478,16 @@ class ColorSafeStringify {
3311
3478
  /* harmony default export */ const libs_ColorSafeStringify = (ColorSafeStringify);
3312
3479
 
3313
3480
  ;// ./src/v1/libs/TinyPromiseQueue.mjs
3481
+ /**
3482
+ * @typedef {Object} QueuedTask
3483
+ * @property {(...args: any[]) => Promise<any>|Promise<any>} task - The async task to execute.
3484
+ * @property {(value: any) => any} resolve - The resolve function from the Promise.
3485
+ * @property {(reason?: any) => any} reject - The reject function from the Promise.
3486
+ * @property {string|undefined} [id] - Optional identifier for the task.
3487
+ * @property {string|null|undefined} [marker] - Optional marker for the task.
3488
+ * @property {number|null|undefined} [delay] - Optional delay (in ms) before the task is executed.
3489
+ */
3490
+
3314
3491
  /**
3315
3492
  * A queue system for managing and executing asynchronous tasks sequentially, one at a time.
3316
3493
  *
@@ -3320,20 +3497,10 @@ class ColorSafeStringify {
3320
3497
  * @class
3321
3498
  */
3322
3499
  class TinyPromiseQueue {
3323
- /**
3324
- * @typedef {Object} QueuedTask
3325
- * @property {(...args: any[]) => Promise<any>|Promise<any>} task - The async task to execute.
3326
- * @property {(value: any) => any} resolve - The resolve function from the Promise.
3327
- * @property {(reason?: any) => any} reject - The reject function from the Promise.
3328
- * @property {string|undefined} [id] - Optional identifier for the task.
3329
- * @property {string|null|undefined} [marker] - Optional marker for the task.
3330
- * @property {number|null|undefined} [delay] - Optional delay (in ms) before the task is executed.
3331
- */
3332
-
3333
- /** @type {Array<QueuedTask>} */
3500
+ /** @type {QueuedTask[]} */
3334
3501
  #queue = [];
3335
3502
  #running = false;
3336
- /** @type {Record<string, *>} */
3503
+ /** @type {Record<string, ReturnType<typeof setTimeout>>} */
3337
3504
  #timeouts = {};
3338
3505
  /** @type {Set<string>} */
3339
3506
  #blacklist = new Set();
@@ -3496,8 +3663,13 @@ class TinyPromiseQueue {
3496
3663
  * @param {(...args: any[]) => Promise<any>|Promise<any>} task A function that returns a Promise.
3497
3664
  * @param {string} [id] Optional ID to identify the task in the queue.
3498
3665
  * @returns {Promise<any>} A Promise that resolves or rejects with the result of the task once it's processed.
3666
+ * @throws {Error} Throws if param is invalid.
3499
3667
  */
3500
3668
  async enqueuePoint(task, id) {
3669
+ if (typeof task !== 'function')
3670
+ return Promise.reject(new Error('Task must be a function returning a Promise.'));
3671
+ if (typeof id !== 'undefined' && typeof id !== 'string')
3672
+ throw new Error('The "id" parameter must be a string.');
3501
3673
  if (!this.#running) return task();
3502
3674
  return new Promise((resolve, reject) => {
3503
3675
  this.#queue.push({ marker: 'POINT_MARKER', task, resolve, reject, id });
@@ -3516,8 +3688,16 @@ class TinyPromiseQueue {
3516
3688
  * @param {number|null} [delay] Optional delay (in ms) before the task is executed.
3517
3689
  * @param {string} [id] Optional ID to identify the task in the queue.
3518
3690
  * @returns {Promise<any>} A Promise that resolves or rejects with the result of the task once it's processed.
3691
+ * @throws {Error} Throws if param is invalid.
3519
3692
  */
3520
3693
  enqueue(task, delay, id) {
3694
+ if (typeof task !== 'function')
3695
+ return Promise.reject(new Error('Task must be a function returning a Promise.'));
3696
+ if (typeof delay !== 'undefined' && (typeof delay !== 'number' || delay < 0))
3697
+ return Promise.reject(new Error('Delay must be a positive number or undefined.'));
3698
+ if (typeof id !== 'undefined' && typeof id !== 'string')
3699
+ throw new Error('The "id" parameter must be a string.');
3700
+
3521
3701
  return new Promise((resolve, reject) => {
3522
3702
  this.#queue.push({ task, resolve, reject, id, delay });
3523
3703
  this.#processQueue();
@@ -3530,9 +3710,10 @@ class TinyPromiseQueue {
3530
3710
  *
3531
3711
  * @param {string} id The ID of the task to cancel.
3532
3712
  * @returns {boolean} True if a delay was cancelled and the task was removed.
3713
+ * @throws {Error} Throws if `id` is not a string.
3533
3714
  */
3534
3715
  cancelTask(id) {
3535
- if (!id) return false;
3716
+ if (typeof id !== 'string') throw new Error('The "id" parameter must be a string.');
3536
3717
  let cancelled = false;
3537
3718
 
3538
3719
  if (id in this.#timeouts) {