@sv443-network/userutils 10.1.0 → 10.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @sv443-network/userutils
2
2
 
3
+ ## 10.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ffca33d: Updated CoreUtils to v3.5.0, which includes the following changes:
8
+ - Added function `createTable()` to create a very flexible ASCII table, including ANSI color and `%c` styling support.
9
+ - Fixed type variance issue in `DataStoreSerializer` where `DataStore` instances with specific data types (e.g. `DataStore<MyType>`) couldn't be passed to the constructor without being asserted `as DataStore<DataStoreData, boolean>`.
10
+
11
+ ## 10.2.0
12
+
13
+ ### Minor Changes
14
+
15
+ - 1f32c2e: Updated CoreUtils to v3.4.0, which includes the following changes:
16
+ - `Debouncer` and `debounce` now have an extra parameter of type `NanoEmitterOptions` to customize the underlying `NanoEmitter` instance.
17
+ - Added function `createRecurringTask()` as a "batteries included" alternative to `setImmediateTimeoutLoop()` and `setImmediateInterval()`, with more ways to control task execution and aborting.
18
+ - Fixed internal event emission problems in `Debouncer`
19
+
3
20
  ## 10.1.0
4
21
 
5
22
  ### Minor Changes
package/README.md CHANGED
@@ -108,6 +108,8 @@ View the documentation of previous major versions:
108
108
  - 🟧 [`class DataStore`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-datastore) - The main class for the data store
109
109
  - 🔷 [`type DataStoreOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-datastoreoptions) - Options for the data store
110
110
  - 🔷 [`type DataMigrationsDict`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-datamigrationsdict) - Dictionary of data migration functions
111
+ - 🔷 [`type DataStoreData`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-datastoredata) - The type of the serializable data
112
+ - 🔷 [`type DataStoreEventMap`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-datastoreeventmap) - Map of DataStore events
111
113
  - 🟧 [`class DataStoreSerializer`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#class-datastoreserializer) - Serializes and deserializes data for multiple DataStore instances
112
114
  - 🔷 [`type DataStoreSerializerOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-datastoreserializeroptions) - Options for the DataStoreSerializer
113
115
  - 🔷 [`type LoadStoresDataResult`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-loadstoresdataresult) - Result of calling [`loadStoresData()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#datastoreserializer-loadstoresdata)
@@ -155,6 +157,8 @@ View the documentation of previous major versions:
155
157
  - 🟣 [`function pureObj()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-pureobj) - Applies an object's props to a null object (object without prototype chain) or just returns a new null object
156
158
  - 🟣 [`function setImmediateInterval()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-setimmediateinterval) - Like `setInterval()`, but instantly calls the callback and supports passing an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
157
159
  - 🟣 [`function setImmediateTimeoutLoop()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-setimmediatetimeoutloop) - Like a recursive `setTimeout()` loop, but instantly calls the callback and supports passing an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
160
+ - 🟣 [`function createRecurringTask()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-createrecurringtask) - Similar to `setImmediateTimeoutLoop()`, but with many more ways of controlling execution.
161
+ - 🔷 [`type RecurringTaskOptions`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#type-recurringtaskoptions) - Options for the `createRecurringTask()` function.
158
162
  - 🟣 [`function scheduleExit()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-scheduleexit) - Schedules a process exit after the next event loop tick, to allow operations like IO writes to finish.
159
163
  - 🟣 [`function getCallStack()`](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#function-getcallstack) - Returns the current call stack, starting at the caller of this function.
160
164
  - [**NanoEmitter:**](https://github.com/Sv443-Network/CoreUtils/blob/main/docs.md#nanoemitter)
@@ -64,6 +64,8 @@ __export(lib_exports, {
64
64
  consumeGen: () => consumeGen,
65
65
  consumeStringGen: () => consumeStringGen,
66
66
  createProgressBar: () => createProgressBar,
67
+ createRecurringTask: () => createRecurringTask,
68
+ createTable: () => createTable,
67
69
  currentDialogId: () => currentDialogId,
68
70
  darkenColor: () => darkenColor,
69
71
  debounce: () => debounce,
@@ -71,6 +73,7 @@ __export(lib_exports, {
71
73
  defaultDialogCss: () => defaultDialogCss,
72
74
  defaultPbChars: () => defaultPbChars,
73
75
  defaultStrings: () => defaultStrings,
76
+ defaultTableLineCharset: () => defaultTableLineCharset,
74
77
  digitCount: () => digitCount,
75
78
  fetchAdvanced: () => fetchAdvanced,
76
79
  formatNumber: () => formatNumber,
@@ -117,7 +120,7 @@ __export(lib_exports, {
117
120
  });
118
121
  module.exports = __toCommonJS(lib_exports);
119
122
 
120
- // node_modules/.pnpm/@sv443-network+coreutils@3.3.0/node_modules/@sv443-network/coreutils/dist/CoreUtils.mjs
123
+ // node_modules/.pnpm/@sv443-network+coreutils@3.5.0/node_modules/@sv443-network/coreutils/dist/CoreUtils.mjs
121
124
  function bitSetHas(bitSet, checkVal) {
122
125
  return (bitSet & checkVal) === checkVal;
123
126
  }
@@ -480,12 +483,46 @@ function getCallStack(asArray, lines = Infinity) {
480
483
  if (typeof lines !== "number" || isNaN(lines) || lines < 0)
481
484
  throw new TypeError("lines parameter must be a non-negative number");
482
485
  try {
483
- throw new Error("This is to capture a stack trace with CoreUtils.getCallStack(). (If you see this somewhere, you can safely ignore it.)");
486
+ throw new CustomError("GetCallStack", "Capturing a stack trace with CoreUtils.getCallStack(). If you see this anywhere, you can safely ignore it.");
484
487
  } catch (err) {
485
488
  const stack = ((_a = err.stack) != null ? _a : "").split("\n").map((line) => line.trim()).slice(2, lines + 2);
486
489
  return asArray !== false ? stack : stack.join("\n");
487
490
  }
488
491
  }
492
+ function createRecurringTask(options) {
493
+ var _a;
494
+ let iterations = 0;
495
+ let aborted = false;
496
+ (_a = options.signal) == null ? void 0 : _a.addEventListener("abort", () => {
497
+ aborted = true;
498
+ }, { once: true });
499
+ const runRecurringTask = async (initial = false) => {
500
+ var _a3, _b;
501
+ var _a2;
502
+ if (aborted)
503
+ return;
504
+ try {
505
+ if (((_a3 = options.immediate) != null ? _a3 : true) || !initial) {
506
+ iterations++;
507
+ if ((_b = await ((_a2 = options.condition) == null ? void 0 : _a2.call(options, iterations - 1))) != null ? _b : true) {
508
+ const val = await options.task(iterations - 1);
509
+ if (options.onSuccess)
510
+ await options.onSuccess(val, iterations - 1);
511
+ }
512
+ }
513
+ } catch (err) {
514
+ if (options.onError)
515
+ await options.onError(err, iterations - 1);
516
+ if (options.abortOnError)
517
+ aborted = true;
518
+ if (!options.onError && !options.abortOnError)
519
+ throw err;
520
+ }
521
+ if (!aborted && (typeof options.maxIterations !== "number" || iterations < options.maxIterations))
522
+ setTimeout(runRecurringTask, options.timeout);
523
+ };
524
+ return runRecurringTask(true);
525
+ }
489
526
  function autoPlural(term, num, pluralType = "auto") {
490
527
  if (typeof num !== "number") {
491
528
  if ("length" in num)
@@ -574,6 +611,179 @@ function truncStr(input, length, endStr = "...") {
574
611
  const finalStr = str.length > length ? str.substring(0, length - endStr.length) + endStr : str;
575
612
  return finalStr.length > length ? finalStr.substring(0, length) : finalStr;
576
613
  }
614
+ var defaultTableLineCharset = {
615
+ single: {
616
+ horizontal: "\u2500",
617
+ vertical: "\u2502",
618
+ topLeft: "\u250C",
619
+ topRight: "\u2510",
620
+ bottomLeft: "\u2514",
621
+ bottomRight: "\u2518",
622
+ leftT: "\u251C",
623
+ rightT: "\u2524",
624
+ topT: "\u252C",
625
+ bottomT: "\u2534",
626
+ cross: "\u253C"
627
+ },
628
+ double: {
629
+ horizontal: "\u2550",
630
+ vertical: "\u2551",
631
+ topLeft: "\u2554",
632
+ topRight: "\u2557",
633
+ bottomLeft: "\u255A",
634
+ bottomRight: "\u255D",
635
+ leftT: "\u2560",
636
+ rightT: "\u2563",
637
+ topT: "\u2566",
638
+ bottomT: "\u2569",
639
+ cross: "\u256C"
640
+ },
641
+ none: {
642
+ horizontal: " ",
643
+ vertical: " ",
644
+ topLeft: " ",
645
+ topRight: " ",
646
+ bottomLeft: " ",
647
+ bottomRight: " ",
648
+ leftT: " ",
649
+ rightT: " ",
650
+ topT: " ",
651
+ bottomT: " ",
652
+ cross: " "
653
+ }
654
+ };
655
+ function createTable(rows, options) {
656
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
657
+ var _a;
658
+ const opts = {
659
+ columnAlign: "left",
660
+ truncateAbove: Infinity,
661
+ truncEndStr: "\u2026",
662
+ minPadding: 1,
663
+ lineStyle: "single",
664
+ applyCellStyle: () => void 0,
665
+ applyLineStyle: () => void 0,
666
+ lineCharset: defaultTableLineCharset,
667
+ ...options != null ? options : {}
668
+ };
669
+ const defRange = (val, min, max) => clamp(typeof val !== "number" || isNaN(Number(val)) ? min : val, min, max);
670
+ opts.truncateAbove = defRange(opts.truncateAbove, 0, Infinity);
671
+ opts.minPadding = defRange(opts.minPadding, 0, Infinity);
672
+ const lnCh = opts.lineCharset[opts.lineStyle];
673
+ const stripAnsi = (str) => str.replace(/\u001b\[[0-9;]*m/g, "");
674
+ const stringRows = rows.map((row) => row.map((cell) => String(cell)));
675
+ const colCount = (_a2 = (_a = rows[0]) == null ? void 0 : _a.length) != null ? _a2 : 0;
676
+ if (colCount === 0 || stringRows.length === 0)
677
+ return "";
678
+ if (isFinite(opts.truncateAbove)) {
679
+ const truncAnsi = (str, maxVisible, endStr) => {
680
+ const limit = maxVisible - endStr.length;
681
+ if (limit <= 0)
682
+ return endStr.slice(0, maxVisible);
683
+ let visible = 0;
684
+ let result = "";
685
+ let i = 0;
686
+ let hasAnsi = false;
687
+ while (i < str.length) {
688
+ if (str[i] === "\x1B" && str[i + 1] === "[") {
689
+ const seqEnd = str.indexOf("m", i + 2);
690
+ if (seqEnd !== -1) {
691
+ result += str.slice(i, seqEnd + 1);
692
+ hasAnsi = true;
693
+ i = seqEnd + 1;
694
+ continue;
695
+ }
696
+ }
697
+ if (visible === limit) {
698
+ result += endStr;
699
+ if (hasAnsi)
700
+ result += "\x1B[0m";
701
+ return result;
702
+ }
703
+ result += str[i];
704
+ visible++;
705
+ i++;
706
+ }
707
+ return result;
708
+ };
709
+ for (const row of stringRows)
710
+ for (let j = 0; j < row.length; j++)
711
+ if (stripAnsi((_b = row[j]) != null ? _b : "").length > opts.truncateAbove)
712
+ row[j] = truncAnsi((_c = row[j]) != null ? _c : "", opts.truncateAbove, opts.truncEndStr);
713
+ }
714
+ const colWidths = Array.from(
715
+ { length: colCount },
716
+ (_, j) => Math.max(0, ...stringRows.map((row) => {
717
+ var _a3;
718
+ return stripAnsi((_a3 = row[j]) != null ? _a3 : "").length;
719
+ }))
720
+ );
721
+ const applyLn = (i, j, ch) => {
722
+ var _a3;
723
+ const [before = "", after = ""] = (_a3 = opts.applyLineStyle(i, j)) != null ? _a3 : [];
724
+ return `${before}${ch}${after}`;
725
+ };
726
+ const buildBorderRow = (lineIdx, leftCh, midCh, rightCh) => {
727
+ var _a3;
728
+ let result = "";
729
+ let j = 0;
730
+ result += applyLn(lineIdx, j++, leftCh);
731
+ for (let col = 0; col < colCount; col++) {
732
+ const cellWidth = ((_a3 = colWidths[col]) != null ? _a3 : 0) + opts.minPadding * 2;
733
+ for (let ci = 0; ci < cellWidth; ci++)
734
+ result += applyLn(lineIdx, j++, lnCh.horizontal);
735
+ if (col < colCount - 1)
736
+ result += applyLn(lineIdx, j++, midCh);
737
+ }
738
+ result += applyLn(lineIdx, j++, rightCh);
739
+ return result;
740
+ };
741
+ const lines = [];
742
+ for (let rowIdx = 0; rowIdx < stringRows.length; rowIdx++) {
743
+ const row = (_d = stringRows[rowIdx]) != null ? _d : [];
744
+ const lineIdxBase = rowIdx * 3;
745
+ if (opts.lineStyle !== "none") {
746
+ lines.push(
747
+ rowIdx === 0 ? buildBorderRow(lineIdxBase, lnCh.topLeft, lnCh.topT, lnCh.topRight) : buildBorderRow(lineIdxBase, lnCh.leftT, lnCh.cross, lnCh.rightT)
748
+ );
749
+ }
750
+ let contentLine = "";
751
+ let j = 0;
752
+ contentLine += applyLn(lineIdxBase + 1, j++, lnCh.vertical);
753
+ for (let colIdx = 0; colIdx < colCount; colIdx++) {
754
+ const cell = (_e = row[colIdx]) != null ? _e : "";
755
+ const visLen = stripAnsi(cell).length;
756
+ const extra = ((_f = colWidths[colIdx]) != null ? _f : 0) - visLen;
757
+ const align = (_g = Array.isArray(opts.columnAlign) ? opts.columnAlign[colIdx] : opts.columnAlign) != null ? _g : "left";
758
+ let leftPad;
759
+ let rightPad;
760
+ switch (align) {
761
+ case "right":
762
+ leftPad = opts.minPadding + extra;
763
+ rightPad = opts.minPadding;
764
+ break;
765
+ case "centerLeft":
766
+ leftPad = opts.minPadding + Math.floor(extra / 2);
767
+ rightPad = opts.minPadding + Math.ceil(extra / 2);
768
+ break;
769
+ case "centerRight":
770
+ leftPad = opts.minPadding + Math.ceil(extra / 2);
771
+ rightPad = opts.minPadding + Math.floor(extra / 2);
772
+ break;
773
+ default:
774
+ leftPad = opts.minPadding;
775
+ rightPad = opts.minPadding + extra;
776
+ }
777
+ const [cellBefore = "", cellAfter = ""] = (_h = opts.applyCellStyle(rowIdx, colIdx)) != null ? _h : [];
778
+ contentLine += " ".repeat(leftPad) + cellBefore + cell + cellAfter + " ".repeat(rightPad);
779
+ contentLine += applyLn(lineIdxBase + 1, j++, lnCh.vertical);
780
+ }
781
+ lines.push(contentLine);
782
+ if (opts.lineStyle !== "none" && rowIdx === stringRows.length - 1)
783
+ lines.push(buildBorderRow(lineIdxBase + 2, lnCh.bottomLeft, lnCh.bottomT, lnCh.bottomRight));
784
+ }
785
+ return lines.join("\n");
786
+ }
577
787
  var createNanoEvents = () => ({
578
788
  emit(event, ...args) {
579
789
  for (let callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) {
@@ -1280,6 +1490,7 @@ var FileStorageEngine = class extends DataStoreEngine {
1280
1490
  var DataStoreSerializer = class _DataStoreSerializer {
1281
1491
  constructor(stores, options = {}) {
1282
1492
  __publicField(this, "stores");
1493
+ // eslint-disable-line @typescript-eslint/no-explicit-any
1283
1494
  __publicField(this, "options");
1284
1495
  if (!crypto || !crypto.subtle)
1285
1496
  throw new ScriptContextError("DataStoreSerializer has to run in a secure context (HTTPS) or in another environment that implements the subtleCrypto API!");
@@ -1291,7 +1502,10 @@ var DataStoreSerializer = class _DataStoreSerializer {
1291
1502
  ...options
1292
1503
  };
1293
1504
  }
1294
- /** Calculates the checksum of a string */
1505
+ /**
1506
+ * Calculates the checksum of a string. Uses {@linkcode computeHash()} with SHA-256 and digests as a hex string by default.
1507
+ * Override this in a subclass if a custom checksum method is needed.
1508
+ */
1295
1509
  async calcChecksum(input) {
1296
1510
  return computeHash(input, "SHA-256");
1297
1511
  }
@@ -1421,8 +1635,8 @@ var Debouncer = class extends NanoEmitter {
1421
1635
  * @param timeout Timeout in milliseconds between letting through calls - defaults to 200
1422
1636
  * @param type The edge type to use for the debouncer - see {@linkcode DebouncerType} for details or [the documentation for an explanation and diagram](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#debouncer) - defaults to "immediate"
1423
1637
  */
1424
- constructor(timeout = 200, type = "immediate") {
1425
- super();
1638
+ constructor(timeout = 200, type = "immediate", nanoEmitterOptions) {
1639
+ super(nanoEmitterOptions);
1426
1640
  /** All registered listener functions and the time they were attached */
1427
1641
  __publicField(this, "listeners", []);
1428
1642
  /** The currently active timeout */
@@ -1453,7 +1667,7 @@ var Debouncer = class extends NanoEmitter {
1453
1667
  //#region timeout
1454
1668
  /** Sets the timeout for the debouncer */
1455
1669
  setTimeout(timeout) {
1456
- this.emit("change", this.timeout = timeout, this.type);
1670
+ this.events.emit("change", this.timeout = timeout, this.type);
1457
1671
  }
1458
1672
  /** Returns the current timeout */
1459
1673
  getTimeout() {
@@ -1466,7 +1680,7 @@ var Debouncer = class extends NanoEmitter {
1466
1680
  //#region type
1467
1681
  /** Sets the edge type for the debouncer */
1468
1682
  setType(type) {
1469
- this.emit("change", this.timeout, this.type = type);
1683
+ this.events.emit("change", this.timeout, this.type = type);
1470
1684
  }
1471
1685
  /** Returns the current edge type */
1472
1686
  getType() {
@@ -1477,7 +1691,7 @@ var Debouncer = class extends NanoEmitter {
1477
1691
  call(...args) {
1478
1692
  const cl = (...a) => {
1479
1693
  this.queuedCall = void 0;
1480
- this.emit("call", ...a);
1694
+ this.events.emit("call", ...a);
1481
1695
  this.listeners.forEach((l) => l.call(this, ...a));
1482
1696
  };
1483
1697
  const setRepeatTimeout = () => {
@@ -1510,8 +1724,8 @@ var Debouncer = class extends NanoEmitter {
1510
1724
  }
1511
1725
  }
1512
1726
  };
1513
- function debounce(fn, timeout = 200, type = "immediate") {
1514
- const debouncer = new Debouncer(timeout, type);
1727
+ function debounce(fn, timeout = 200, type = "immediate", nanoEmitterOptions) {
1728
+ const debouncer = new Debouncer(timeout, type, nanoEmitterOptions);
1515
1729
  debouncer.addListener(fn);
1516
1730
  const func = ((...args) => debouncer.call(...args));
1517
1731
  func.debouncer = debouncer;
@@ -1520,8 +1734,8 @@ function debounce(fn, timeout = 200, type = "immediate") {
1520
1734
 
1521
1735
  // lib/consts.ts
1522
1736
  var rawConsts = {
1523
- coreUtilsVersion: "3.3.0",
1524
- userUtilsVersion: "10.1.0"
1737
+ coreUtilsVersion: "3.5.0",
1738
+ userUtilsVersion: "10.3.0"
1525
1739
  };
1526
1740
  function getConst(constKey, defaultVal) {
1527
1741
  const val = rawConsts[constKey];
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
 
5
- // node_modules/.pnpm/@sv443-network+coreutils@3.3.0/node_modules/@sv443-network/coreutils/dist/CoreUtils.mjs
5
+ // node_modules/.pnpm/@sv443-network+coreutils@3.5.0/node_modules/@sv443-network/coreutils/dist/CoreUtils.mjs
6
6
  function bitSetHas(bitSet, checkVal) {
7
7
  return (bitSet & checkVal) === checkVal;
8
8
  }
@@ -365,12 +365,46 @@ function getCallStack(asArray, lines = Infinity) {
365
365
  if (typeof lines !== "number" || isNaN(lines) || lines < 0)
366
366
  throw new TypeError("lines parameter must be a non-negative number");
367
367
  try {
368
- throw new Error("This is to capture a stack trace with CoreUtils.getCallStack(). (If you see this somewhere, you can safely ignore it.)");
368
+ throw new CustomError("GetCallStack", "Capturing a stack trace with CoreUtils.getCallStack(). If you see this anywhere, you can safely ignore it.");
369
369
  } catch (err) {
370
370
  const stack = ((_a = err.stack) != null ? _a : "").split("\n").map((line) => line.trim()).slice(2, lines + 2);
371
371
  return asArray !== false ? stack : stack.join("\n");
372
372
  }
373
373
  }
374
+ function createRecurringTask(options) {
375
+ var _a;
376
+ let iterations = 0;
377
+ let aborted = false;
378
+ (_a = options.signal) == null ? void 0 : _a.addEventListener("abort", () => {
379
+ aborted = true;
380
+ }, { once: true });
381
+ const runRecurringTask = async (initial = false) => {
382
+ var _a3, _b;
383
+ var _a2;
384
+ if (aborted)
385
+ return;
386
+ try {
387
+ if (((_a3 = options.immediate) != null ? _a3 : true) || !initial) {
388
+ iterations++;
389
+ if ((_b = await ((_a2 = options.condition) == null ? void 0 : _a2.call(options, iterations - 1))) != null ? _b : true) {
390
+ const val = await options.task(iterations - 1);
391
+ if (options.onSuccess)
392
+ await options.onSuccess(val, iterations - 1);
393
+ }
394
+ }
395
+ } catch (err) {
396
+ if (options.onError)
397
+ await options.onError(err, iterations - 1);
398
+ if (options.abortOnError)
399
+ aborted = true;
400
+ if (!options.onError && !options.abortOnError)
401
+ throw err;
402
+ }
403
+ if (!aborted && (typeof options.maxIterations !== "number" || iterations < options.maxIterations))
404
+ setTimeout(runRecurringTask, options.timeout);
405
+ };
406
+ return runRecurringTask(true);
407
+ }
374
408
  function autoPlural(term, num, pluralType = "auto") {
375
409
  if (typeof num !== "number") {
376
410
  if ("length" in num)
@@ -459,6 +493,179 @@ function truncStr(input, length, endStr = "...") {
459
493
  const finalStr = str.length > length ? str.substring(0, length - endStr.length) + endStr : str;
460
494
  return finalStr.length > length ? finalStr.substring(0, length) : finalStr;
461
495
  }
496
+ var defaultTableLineCharset = {
497
+ single: {
498
+ horizontal: "\u2500",
499
+ vertical: "\u2502",
500
+ topLeft: "\u250C",
501
+ topRight: "\u2510",
502
+ bottomLeft: "\u2514",
503
+ bottomRight: "\u2518",
504
+ leftT: "\u251C",
505
+ rightT: "\u2524",
506
+ topT: "\u252C",
507
+ bottomT: "\u2534",
508
+ cross: "\u253C"
509
+ },
510
+ double: {
511
+ horizontal: "\u2550",
512
+ vertical: "\u2551",
513
+ topLeft: "\u2554",
514
+ topRight: "\u2557",
515
+ bottomLeft: "\u255A",
516
+ bottomRight: "\u255D",
517
+ leftT: "\u2560",
518
+ rightT: "\u2563",
519
+ topT: "\u2566",
520
+ bottomT: "\u2569",
521
+ cross: "\u256C"
522
+ },
523
+ none: {
524
+ horizontal: " ",
525
+ vertical: " ",
526
+ topLeft: " ",
527
+ topRight: " ",
528
+ bottomLeft: " ",
529
+ bottomRight: " ",
530
+ leftT: " ",
531
+ rightT: " ",
532
+ topT: " ",
533
+ bottomT: " ",
534
+ cross: " "
535
+ }
536
+ };
537
+ function createTable(rows, options) {
538
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
539
+ var _a;
540
+ const opts = {
541
+ columnAlign: "left",
542
+ truncateAbove: Infinity,
543
+ truncEndStr: "\u2026",
544
+ minPadding: 1,
545
+ lineStyle: "single",
546
+ applyCellStyle: () => void 0,
547
+ applyLineStyle: () => void 0,
548
+ lineCharset: defaultTableLineCharset,
549
+ ...options != null ? options : {}
550
+ };
551
+ const defRange = (val, min, max) => clamp(typeof val !== "number" || isNaN(Number(val)) ? min : val, min, max);
552
+ opts.truncateAbove = defRange(opts.truncateAbove, 0, Infinity);
553
+ opts.minPadding = defRange(opts.minPadding, 0, Infinity);
554
+ const lnCh = opts.lineCharset[opts.lineStyle];
555
+ const stripAnsi = (str) => str.replace(/\u001b\[[0-9;]*m/g, "");
556
+ const stringRows = rows.map((row) => row.map((cell) => String(cell)));
557
+ const colCount = (_a2 = (_a = rows[0]) == null ? void 0 : _a.length) != null ? _a2 : 0;
558
+ if (colCount === 0 || stringRows.length === 0)
559
+ return "";
560
+ if (isFinite(opts.truncateAbove)) {
561
+ const truncAnsi = (str, maxVisible, endStr) => {
562
+ const limit = maxVisible - endStr.length;
563
+ if (limit <= 0)
564
+ return endStr.slice(0, maxVisible);
565
+ let visible = 0;
566
+ let result = "";
567
+ let i = 0;
568
+ let hasAnsi = false;
569
+ while (i < str.length) {
570
+ if (str[i] === "\x1B" && str[i + 1] === "[") {
571
+ const seqEnd = str.indexOf("m", i + 2);
572
+ if (seqEnd !== -1) {
573
+ result += str.slice(i, seqEnd + 1);
574
+ hasAnsi = true;
575
+ i = seqEnd + 1;
576
+ continue;
577
+ }
578
+ }
579
+ if (visible === limit) {
580
+ result += endStr;
581
+ if (hasAnsi)
582
+ result += "\x1B[0m";
583
+ return result;
584
+ }
585
+ result += str[i];
586
+ visible++;
587
+ i++;
588
+ }
589
+ return result;
590
+ };
591
+ for (const row of stringRows)
592
+ for (let j = 0; j < row.length; j++)
593
+ if (stripAnsi((_b = row[j]) != null ? _b : "").length > opts.truncateAbove)
594
+ row[j] = truncAnsi((_c = row[j]) != null ? _c : "", opts.truncateAbove, opts.truncEndStr);
595
+ }
596
+ const colWidths = Array.from(
597
+ { length: colCount },
598
+ (_, j) => Math.max(0, ...stringRows.map((row) => {
599
+ var _a3;
600
+ return stripAnsi((_a3 = row[j]) != null ? _a3 : "").length;
601
+ }))
602
+ );
603
+ const applyLn = (i, j, ch) => {
604
+ var _a3;
605
+ const [before = "", after = ""] = (_a3 = opts.applyLineStyle(i, j)) != null ? _a3 : [];
606
+ return `${before}${ch}${after}`;
607
+ };
608
+ const buildBorderRow = (lineIdx, leftCh, midCh, rightCh) => {
609
+ var _a3;
610
+ let result = "";
611
+ let j = 0;
612
+ result += applyLn(lineIdx, j++, leftCh);
613
+ for (let col = 0; col < colCount; col++) {
614
+ const cellWidth = ((_a3 = colWidths[col]) != null ? _a3 : 0) + opts.minPadding * 2;
615
+ for (let ci = 0; ci < cellWidth; ci++)
616
+ result += applyLn(lineIdx, j++, lnCh.horizontal);
617
+ if (col < colCount - 1)
618
+ result += applyLn(lineIdx, j++, midCh);
619
+ }
620
+ result += applyLn(lineIdx, j++, rightCh);
621
+ return result;
622
+ };
623
+ const lines = [];
624
+ for (let rowIdx = 0; rowIdx < stringRows.length; rowIdx++) {
625
+ const row = (_d = stringRows[rowIdx]) != null ? _d : [];
626
+ const lineIdxBase = rowIdx * 3;
627
+ if (opts.lineStyle !== "none") {
628
+ lines.push(
629
+ rowIdx === 0 ? buildBorderRow(lineIdxBase, lnCh.topLeft, lnCh.topT, lnCh.topRight) : buildBorderRow(lineIdxBase, lnCh.leftT, lnCh.cross, lnCh.rightT)
630
+ );
631
+ }
632
+ let contentLine = "";
633
+ let j = 0;
634
+ contentLine += applyLn(lineIdxBase + 1, j++, lnCh.vertical);
635
+ for (let colIdx = 0; colIdx < colCount; colIdx++) {
636
+ const cell = (_e = row[colIdx]) != null ? _e : "";
637
+ const visLen = stripAnsi(cell).length;
638
+ const extra = ((_f = colWidths[colIdx]) != null ? _f : 0) - visLen;
639
+ const align = (_g = Array.isArray(opts.columnAlign) ? opts.columnAlign[colIdx] : opts.columnAlign) != null ? _g : "left";
640
+ let leftPad;
641
+ let rightPad;
642
+ switch (align) {
643
+ case "right":
644
+ leftPad = opts.minPadding + extra;
645
+ rightPad = opts.minPadding;
646
+ break;
647
+ case "centerLeft":
648
+ leftPad = opts.minPadding + Math.floor(extra / 2);
649
+ rightPad = opts.minPadding + Math.ceil(extra / 2);
650
+ break;
651
+ case "centerRight":
652
+ leftPad = opts.minPadding + Math.ceil(extra / 2);
653
+ rightPad = opts.minPadding + Math.floor(extra / 2);
654
+ break;
655
+ default:
656
+ leftPad = opts.minPadding;
657
+ rightPad = opts.minPadding + extra;
658
+ }
659
+ const [cellBefore = "", cellAfter = ""] = (_h = opts.applyCellStyle(rowIdx, colIdx)) != null ? _h : [];
660
+ contentLine += " ".repeat(leftPad) + cellBefore + cell + cellAfter + " ".repeat(rightPad);
661
+ contentLine += applyLn(lineIdxBase + 1, j++, lnCh.vertical);
662
+ }
663
+ lines.push(contentLine);
664
+ if (opts.lineStyle !== "none" && rowIdx === stringRows.length - 1)
665
+ lines.push(buildBorderRow(lineIdxBase + 2, lnCh.bottomLeft, lnCh.bottomT, lnCh.bottomRight));
666
+ }
667
+ return lines.join("\n");
668
+ }
462
669
  var createNanoEvents = () => ({
463
670
  emit(event, ...args) {
464
671
  for (let callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) {
@@ -1165,6 +1372,7 @@ var FileStorageEngine = class extends DataStoreEngine {
1165
1372
  var DataStoreSerializer = class _DataStoreSerializer {
1166
1373
  constructor(stores, options = {}) {
1167
1374
  __publicField(this, "stores");
1375
+ // eslint-disable-line @typescript-eslint/no-explicit-any
1168
1376
  __publicField(this, "options");
1169
1377
  if (!crypto || !crypto.subtle)
1170
1378
  throw new ScriptContextError("DataStoreSerializer has to run in a secure context (HTTPS) or in another environment that implements the subtleCrypto API!");
@@ -1176,7 +1384,10 @@ var DataStoreSerializer = class _DataStoreSerializer {
1176
1384
  ...options
1177
1385
  };
1178
1386
  }
1179
- /** Calculates the checksum of a string */
1387
+ /**
1388
+ * Calculates the checksum of a string. Uses {@linkcode computeHash()} with SHA-256 and digests as a hex string by default.
1389
+ * Override this in a subclass if a custom checksum method is needed.
1390
+ */
1180
1391
  async calcChecksum(input) {
1181
1392
  return computeHash(input, "SHA-256");
1182
1393
  }
@@ -1306,8 +1517,8 @@ var Debouncer = class extends NanoEmitter {
1306
1517
  * @param timeout Timeout in milliseconds between letting through calls - defaults to 200
1307
1518
  * @param type The edge type to use for the debouncer - see {@linkcode DebouncerType} for details or [the documentation for an explanation and diagram](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#debouncer) - defaults to "immediate"
1308
1519
  */
1309
- constructor(timeout = 200, type = "immediate") {
1310
- super();
1520
+ constructor(timeout = 200, type = "immediate", nanoEmitterOptions) {
1521
+ super(nanoEmitterOptions);
1311
1522
  /** All registered listener functions and the time they were attached */
1312
1523
  __publicField(this, "listeners", []);
1313
1524
  /** The currently active timeout */
@@ -1338,7 +1549,7 @@ var Debouncer = class extends NanoEmitter {
1338
1549
  //#region timeout
1339
1550
  /** Sets the timeout for the debouncer */
1340
1551
  setTimeout(timeout) {
1341
- this.emit("change", this.timeout = timeout, this.type);
1552
+ this.events.emit("change", this.timeout = timeout, this.type);
1342
1553
  }
1343
1554
  /** Returns the current timeout */
1344
1555
  getTimeout() {
@@ -1351,7 +1562,7 @@ var Debouncer = class extends NanoEmitter {
1351
1562
  //#region type
1352
1563
  /** Sets the edge type for the debouncer */
1353
1564
  setType(type) {
1354
- this.emit("change", this.timeout, this.type = type);
1565
+ this.events.emit("change", this.timeout, this.type = type);
1355
1566
  }
1356
1567
  /** Returns the current edge type */
1357
1568
  getType() {
@@ -1362,7 +1573,7 @@ var Debouncer = class extends NanoEmitter {
1362
1573
  call(...args) {
1363
1574
  const cl = (...a) => {
1364
1575
  this.queuedCall = void 0;
1365
- this.emit("call", ...a);
1576
+ this.events.emit("call", ...a);
1366
1577
  this.listeners.forEach((l) => l.call(this, ...a));
1367
1578
  };
1368
1579
  const setRepeatTimeout = () => {
@@ -1395,8 +1606,8 @@ var Debouncer = class extends NanoEmitter {
1395
1606
  }
1396
1607
  }
1397
1608
  };
1398
- function debounce(fn, timeout = 200, type = "immediate") {
1399
- const debouncer = new Debouncer(timeout, type);
1609
+ function debounce(fn, timeout = 200, type = "immediate", nanoEmitterOptions) {
1610
+ const debouncer = new Debouncer(timeout, type, nanoEmitterOptions);
1400
1611
  debouncer.addListener(fn);
1401
1612
  const func = ((...args) => debouncer.call(...args));
1402
1613
  func.debouncer = debouncer;
@@ -1405,8 +1616,8 @@ function debounce(fn, timeout = 200, type = "immediate") {
1405
1616
 
1406
1617
  // lib/consts.ts
1407
1618
  var rawConsts = {
1408
- coreUtilsVersion: "3.3.0",
1409
- userUtilsVersion: "10.1.0"
1619
+ coreUtilsVersion: "3.5.0",
1620
+ userUtilsVersion: "10.3.0"
1410
1621
  };
1411
1622
  function getConst(constKey, defaultVal) {
1412
1623
  const val = rawConsts[constKey];
@@ -2640,6 +2851,8 @@ export {
2640
2851
  consumeGen,
2641
2852
  consumeStringGen,
2642
2853
  createProgressBar,
2854
+ createRecurringTask,
2855
+ createTable,
2643
2856
  currentDialogId,
2644
2857
  darkenColor,
2645
2858
  debounce,
@@ -2647,6 +2860,7 @@ export {
2647
2860
  defaultDialogCss,
2648
2861
  defaultPbChars,
2649
2862
  defaultStrings,
2863
+ defaultTableLineCharset,
2650
2864
  digitCount,
2651
2865
  fetchAdvanced,
2652
2866
  formatNumber,
@@ -131,6 +131,8 @@ __export(lib_exports, {
131
131
  consumeGen: () => consumeGen,
132
132
  consumeStringGen: () => consumeStringGen,
133
133
  createProgressBar: () => createProgressBar,
134
+ createRecurringTask: () => createRecurringTask,
135
+ createTable: () => createTable,
134
136
  currentDialogId: () => currentDialogId,
135
137
  darkenColor: () => darkenColor,
136
138
  debounce: () => debounce,
@@ -138,6 +140,7 @@ __export(lib_exports, {
138
140
  defaultDialogCss: () => defaultDialogCss,
139
141
  defaultPbChars: () => defaultPbChars,
140
142
  defaultStrings: () => defaultStrings,
143
+ defaultTableLineCharset: () => defaultTableLineCharset,
141
144
  digitCount: () => digitCount,
142
145
  fetchAdvanced: () => fetchAdvanced,
143
146
  formatNumber: () => formatNumber,
@@ -184,7 +187,7 @@ __export(lib_exports, {
184
187
  });
185
188
  module.exports = __toCommonJS(lib_exports);
186
189
 
187
- // node_modules/.pnpm/@sv443-network+coreutils@3.3.0/node_modules/@sv443-network/coreutils/dist/CoreUtils.mjs
190
+ // node_modules/.pnpm/@sv443-network+coreutils@3.5.0/node_modules/@sv443-network/coreutils/dist/CoreUtils.mjs
188
191
  function bitSetHas(bitSet, checkVal) {
189
192
  return (bitSet & checkVal) === checkVal;
190
193
  }
@@ -556,12 +559,46 @@ function getCallStack(asArray, lines = Infinity) {
556
559
  if (typeof lines !== "number" || isNaN(lines) || lines < 0)
557
560
  throw new TypeError("lines parameter must be a non-negative number");
558
561
  try {
559
- throw new Error("This is to capture a stack trace with CoreUtils.getCallStack(). (If you see this somewhere, you can safely ignore it.)");
562
+ throw new CustomError("GetCallStack", "Capturing a stack trace with CoreUtils.getCallStack(). If you see this anywhere, you can safely ignore it.");
560
563
  } catch (err) {
561
564
  const stack = ((_a = err.stack) != null ? _a : "").split("\n").map((line) => line.trim()).slice(2, lines + 2);
562
565
  return asArray !== false ? stack : stack.join("\n");
563
566
  }
564
567
  }
568
+ function createRecurringTask(options) {
569
+ var _a;
570
+ let iterations = 0;
571
+ let aborted = false;
572
+ (_a = options.signal) == null ? void 0 : _a.addEventListener("abort", () => {
573
+ aborted = true;
574
+ }, { once: true });
575
+ const runRecurringTask = (initial = false) => __async(null, null, function* () {
576
+ var _a3, _b;
577
+ var _a2;
578
+ if (aborted)
579
+ return;
580
+ try {
581
+ if (((_a3 = options.immediate) != null ? _a3 : true) || !initial) {
582
+ iterations++;
583
+ if ((_b = yield (_a2 = options.condition) == null ? void 0 : _a2.call(options, iterations - 1)) != null ? _b : true) {
584
+ const val = yield options.task(iterations - 1);
585
+ if (options.onSuccess)
586
+ yield options.onSuccess(val, iterations - 1);
587
+ }
588
+ }
589
+ } catch (err) {
590
+ if (options.onError)
591
+ yield options.onError(err, iterations - 1);
592
+ if (options.abortOnError)
593
+ aborted = true;
594
+ if (!options.onError && !options.abortOnError)
595
+ throw err;
596
+ }
597
+ if (!aborted && (typeof options.maxIterations !== "number" || iterations < options.maxIterations))
598
+ setTimeout(runRecurringTask, options.timeout);
599
+ });
600
+ return runRecurringTask(true);
601
+ }
565
602
  function autoPlural(term, num, pluralType = "auto") {
566
603
  if (typeof num !== "number") {
567
604
  if ("length" in num)
@@ -650,6 +687,178 @@ function truncStr(input, length, endStr = "...") {
650
687
  const finalStr = str.length > length ? str.substring(0, length - endStr.length) + endStr : str;
651
688
  return finalStr.length > length ? finalStr.substring(0, length) : finalStr;
652
689
  }
690
+ var defaultTableLineCharset = {
691
+ single: {
692
+ horizontal: "\u2500",
693
+ vertical: "\u2502",
694
+ topLeft: "\u250C",
695
+ topRight: "\u2510",
696
+ bottomLeft: "\u2514",
697
+ bottomRight: "\u2518",
698
+ leftT: "\u251C",
699
+ rightT: "\u2524",
700
+ topT: "\u252C",
701
+ bottomT: "\u2534",
702
+ cross: "\u253C"
703
+ },
704
+ double: {
705
+ horizontal: "\u2550",
706
+ vertical: "\u2551",
707
+ topLeft: "\u2554",
708
+ topRight: "\u2557",
709
+ bottomLeft: "\u255A",
710
+ bottomRight: "\u255D",
711
+ leftT: "\u2560",
712
+ rightT: "\u2563",
713
+ topT: "\u2566",
714
+ bottomT: "\u2569",
715
+ cross: "\u256C"
716
+ },
717
+ none: {
718
+ horizontal: " ",
719
+ vertical: " ",
720
+ topLeft: " ",
721
+ topRight: " ",
722
+ bottomLeft: " ",
723
+ bottomRight: " ",
724
+ leftT: " ",
725
+ rightT: " ",
726
+ topT: " ",
727
+ bottomT: " ",
728
+ cross: " "
729
+ }
730
+ };
731
+ function createTable(rows, options) {
732
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
733
+ var _a;
734
+ const opts = __spreadValues({
735
+ columnAlign: "left",
736
+ truncateAbove: Infinity,
737
+ truncEndStr: "\u2026",
738
+ minPadding: 1,
739
+ lineStyle: "single",
740
+ applyCellStyle: () => void 0,
741
+ applyLineStyle: () => void 0,
742
+ lineCharset: defaultTableLineCharset
743
+ }, options != null ? options : {});
744
+ const defRange = (val, min, max) => clamp(typeof val !== "number" || isNaN(Number(val)) ? min : val, min, max);
745
+ opts.truncateAbove = defRange(opts.truncateAbove, 0, Infinity);
746
+ opts.minPadding = defRange(opts.minPadding, 0, Infinity);
747
+ const lnCh = opts.lineCharset[opts.lineStyle];
748
+ const stripAnsi = (str) => str.replace(/\u001b\[[0-9;]*m/g, "");
749
+ const stringRows = rows.map((row) => row.map((cell) => String(cell)));
750
+ const colCount = (_a2 = (_a = rows[0]) == null ? void 0 : _a.length) != null ? _a2 : 0;
751
+ if (colCount === 0 || stringRows.length === 0)
752
+ return "";
753
+ if (isFinite(opts.truncateAbove)) {
754
+ const truncAnsi = (str, maxVisible, endStr) => {
755
+ const limit = maxVisible - endStr.length;
756
+ if (limit <= 0)
757
+ return endStr.slice(0, maxVisible);
758
+ let visible = 0;
759
+ let result = "";
760
+ let i = 0;
761
+ let hasAnsi = false;
762
+ while (i < str.length) {
763
+ if (str[i] === "\x1B" && str[i + 1] === "[") {
764
+ const seqEnd = str.indexOf("m", i + 2);
765
+ if (seqEnd !== -1) {
766
+ result += str.slice(i, seqEnd + 1);
767
+ hasAnsi = true;
768
+ i = seqEnd + 1;
769
+ continue;
770
+ }
771
+ }
772
+ if (visible === limit) {
773
+ result += endStr;
774
+ if (hasAnsi)
775
+ result += "\x1B[0m";
776
+ return result;
777
+ }
778
+ result += str[i];
779
+ visible++;
780
+ i++;
781
+ }
782
+ return result;
783
+ };
784
+ for (const row of stringRows)
785
+ for (let j = 0; j < row.length; j++)
786
+ if (stripAnsi((_b = row[j]) != null ? _b : "").length > opts.truncateAbove)
787
+ row[j] = truncAnsi((_c = row[j]) != null ? _c : "", opts.truncateAbove, opts.truncEndStr);
788
+ }
789
+ const colWidths = Array.from(
790
+ { length: colCount },
791
+ (_, j) => Math.max(0, ...stringRows.map((row) => {
792
+ var _a3;
793
+ return stripAnsi((_a3 = row[j]) != null ? _a3 : "").length;
794
+ }))
795
+ );
796
+ const applyLn = (i, j, ch) => {
797
+ var _a3;
798
+ const [before = "", after = ""] = (_a3 = opts.applyLineStyle(i, j)) != null ? _a3 : [];
799
+ return `${before}${ch}${after}`;
800
+ };
801
+ const buildBorderRow = (lineIdx, leftCh, midCh, rightCh) => {
802
+ var _a3;
803
+ let result = "";
804
+ let j = 0;
805
+ result += applyLn(lineIdx, j++, leftCh);
806
+ for (let col = 0; col < colCount; col++) {
807
+ const cellWidth = ((_a3 = colWidths[col]) != null ? _a3 : 0) + opts.minPadding * 2;
808
+ for (let ci = 0; ci < cellWidth; ci++)
809
+ result += applyLn(lineIdx, j++, lnCh.horizontal);
810
+ if (col < colCount - 1)
811
+ result += applyLn(lineIdx, j++, midCh);
812
+ }
813
+ result += applyLn(lineIdx, j++, rightCh);
814
+ return result;
815
+ };
816
+ const lines = [];
817
+ for (let rowIdx = 0; rowIdx < stringRows.length; rowIdx++) {
818
+ const row = (_d = stringRows[rowIdx]) != null ? _d : [];
819
+ const lineIdxBase = rowIdx * 3;
820
+ if (opts.lineStyle !== "none") {
821
+ lines.push(
822
+ rowIdx === 0 ? buildBorderRow(lineIdxBase, lnCh.topLeft, lnCh.topT, lnCh.topRight) : buildBorderRow(lineIdxBase, lnCh.leftT, lnCh.cross, lnCh.rightT)
823
+ );
824
+ }
825
+ let contentLine = "";
826
+ let j = 0;
827
+ contentLine += applyLn(lineIdxBase + 1, j++, lnCh.vertical);
828
+ for (let colIdx = 0; colIdx < colCount; colIdx++) {
829
+ const cell = (_e = row[colIdx]) != null ? _e : "";
830
+ const visLen = stripAnsi(cell).length;
831
+ const extra = ((_f = colWidths[colIdx]) != null ? _f : 0) - visLen;
832
+ const align = (_g = Array.isArray(opts.columnAlign) ? opts.columnAlign[colIdx] : opts.columnAlign) != null ? _g : "left";
833
+ let leftPad;
834
+ let rightPad;
835
+ switch (align) {
836
+ case "right":
837
+ leftPad = opts.minPadding + extra;
838
+ rightPad = opts.minPadding;
839
+ break;
840
+ case "centerLeft":
841
+ leftPad = opts.minPadding + Math.floor(extra / 2);
842
+ rightPad = opts.minPadding + Math.ceil(extra / 2);
843
+ break;
844
+ case "centerRight":
845
+ leftPad = opts.minPadding + Math.ceil(extra / 2);
846
+ rightPad = opts.minPadding + Math.floor(extra / 2);
847
+ break;
848
+ default:
849
+ leftPad = opts.minPadding;
850
+ rightPad = opts.minPadding + extra;
851
+ }
852
+ const [cellBefore = "", cellAfter = ""] = (_h = opts.applyCellStyle(rowIdx, colIdx)) != null ? _h : [];
853
+ contentLine += " ".repeat(leftPad) + cellBefore + cell + cellAfter + " ".repeat(rightPad);
854
+ contentLine += applyLn(lineIdxBase + 1, j++, lnCh.vertical);
855
+ }
856
+ lines.push(contentLine);
857
+ if (opts.lineStyle !== "none" && rowIdx === stringRows.length - 1)
858
+ lines.push(buildBorderRow(lineIdxBase + 2, lnCh.bottomLeft, lnCh.bottomT, lnCh.bottomRight));
859
+ }
860
+ return lines.join("\n");
861
+ }
653
862
  var createNanoEvents = () => ({
654
863
  emit(event, ...args) {
655
864
  for (let callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) {
@@ -1388,6 +1597,7 @@ var FileStorageEngine = class extends DataStoreEngine {
1388
1597
  var DataStoreSerializer = class _DataStoreSerializer {
1389
1598
  constructor(stores, options = {}) {
1390
1599
  __publicField(this, "stores");
1600
+ // eslint-disable-line @typescript-eslint/no-explicit-any
1391
1601
  __publicField(this, "options");
1392
1602
  if (!crypto || !crypto.subtle)
1393
1603
  throw new ScriptContextError("DataStoreSerializer has to run in a secure context (HTTPS) or in another environment that implements the subtleCrypto API!");
@@ -1398,7 +1608,10 @@ var DataStoreSerializer = class _DataStoreSerializer {
1398
1608
  remapIds: {}
1399
1609
  }, options);
1400
1610
  }
1401
- /** Calculates the checksum of a string */
1611
+ /**
1612
+ * Calculates the checksum of a string. Uses {@linkcode computeHash()} with SHA-256 and digests as a hex string by default.
1613
+ * Override this in a subclass if a custom checksum method is needed.
1614
+ */
1402
1615
  calcChecksum(input) {
1403
1616
  return __async(this, null, function* () {
1404
1617
  return computeHash(input, "SHA-256");
@@ -1546,8 +1759,8 @@ var Debouncer = class extends NanoEmitter {
1546
1759
  * @param timeout Timeout in milliseconds between letting through calls - defaults to 200
1547
1760
  * @param type The edge type to use for the debouncer - see {@linkcode DebouncerType} for details or [the documentation for an explanation and diagram](https://github.com/Sv443-Network/UserUtils/blob/main/docs.md#debouncer) - defaults to "immediate"
1548
1761
  */
1549
- constructor(timeout = 200, type = "immediate") {
1550
- super();
1762
+ constructor(timeout = 200, type = "immediate", nanoEmitterOptions) {
1763
+ super(nanoEmitterOptions);
1551
1764
  /** All registered listener functions and the time they were attached */
1552
1765
  __publicField(this, "listeners", []);
1553
1766
  /** The currently active timeout */
@@ -1578,7 +1791,7 @@ var Debouncer = class extends NanoEmitter {
1578
1791
  //#region timeout
1579
1792
  /** Sets the timeout for the debouncer */
1580
1793
  setTimeout(timeout) {
1581
- this.emit("change", this.timeout = timeout, this.type);
1794
+ this.events.emit("change", this.timeout = timeout, this.type);
1582
1795
  }
1583
1796
  /** Returns the current timeout */
1584
1797
  getTimeout() {
@@ -1591,7 +1804,7 @@ var Debouncer = class extends NanoEmitter {
1591
1804
  //#region type
1592
1805
  /** Sets the edge type for the debouncer */
1593
1806
  setType(type) {
1594
- this.emit("change", this.timeout, this.type = type);
1807
+ this.events.emit("change", this.timeout, this.type = type);
1595
1808
  }
1596
1809
  /** Returns the current edge type */
1597
1810
  getType() {
@@ -1602,7 +1815,7 @@ var Debouncer = class extends NanoEmitter {
1602
1815
  call(...args) {
1603
1816
  const cl = (...a) => {
1604
1817
  this.queuedCall = void 0;
1605
- this.emit("call", ...a);
1818
+ this.events.emit("call", ...a);
1606
1819
  this.listeners.forEach((l) => l.call(this, ...a));
1607
1820
  };
1608
1821
  const setRepeatTimeout = () => {
@@ -1635,8 +1848,8 @@ var Debouncer = class extends NanoEmitter {
1635
1848
  }
1636
1849
  }
1637
1850
  };
1638
- function debounce(fn, timeout = 200, type = "immediate") {
1639
- const debouncer = new Debouncer(timeout, type);
1851
+ function debounce(fn, timeout = 200, type = "immediate", nanoEmitterOptions) {
1852
+ const debouncer = new Debouncer(timeout, type, nanoEmitterOptions);
1640
1853
  debouncer.addListener(fn);
1641
1854
  const func = ((...args) => debouncer.call(...args));
1642
1855
  func.debouncer = debouncer;
@@ -1645,8 +1858,8 @@ function debounce(fn, timeout = 200, type = "immediate") {
1645
1858
 
1646
1859
  // lib/consts.ts
1647
1860
  var rawConsts = {
1648
- coreUtilsVersion: "3.3.0",
1649
- userUtilsVersion: "10.1.0"
1861
+ coreUtilsVersion: "3.5.0",
1862
+ userUtilsVersion: "10.3.0"
1650
1863
  };
1651
1864
  function getConst(constKey, defaultVal) {
1652
1865
  const val = rawConsts[constKey];
@@ -1,7 +1,2 @@
1
1
  /** Contains the semver version strings of UserUtils and the bundled library CoreUtils. */
2
- export declare const versions: {
3
- /** Semver version string of the bundled library CoreUtils. */
4
- CoreUtils: string;
5
- /** Semver version string of UserUtils. */
6
- UserUtils: string;
7
- };
2
+ export declare const versions: Record<"CoreUtils" | "UserUtils", string>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sv443-network/userutils",
3
3
  "libName": "UserUtils",
4
- "version": "10.1.0",
4
+ "version": "10.3.0",
5
5
  "description": "General purpose DOM/GreaseMonkey library that allows you to register listeners for when CSS selectors exist, intercept events, create persistent & synchronous data stores, modify the DOM more easily and much more",
6
6
  "main": "dist/UserUtils.mjs",
7
7
  "module": "dist/UserUtils.mjs",
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "homepage": "https://github.com/Sv443-Network/UserUtils",
35
35
  "dependencies": {
36
- "@sv443-network/coreutils": "3.3.0",
36
+ "@sv443-network/coreutils": "3.5.0",
37
37
  "nanoevents": "9.1.0"
38
38
  },
39
39
  "devDependencies": {