@sv443-network/userutils 9.2.1 → 9.4.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/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { createNanoEvents } from 'nanoevents';
2
2
 
3
3
  var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
6
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -16,6 +18,7 @@ var __spreadValues = (a, b) => {
16
18
  }
17
19
  return a;
18
20
  };
21
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
19
22
  var __objRest = (source, exclude) => {
20
23
  var target = {};
21
24
  for (var prop in source)
@@ -248,16 +251,16 @@ function addGlobalStyle(style) {
248
251
  function preloadImages(srcUrls, rejects = false) {
249
252
  const promises = srcUrls.map((src) => new Promise((res, rej) => {
250
253
  const image = new Image();
251
- image.src = src;
252
254
  image.addEventListener("load", () => res(image));
253
255
  image.addEventListener("error", (evt) => rejects && rej(evt));
256
+ image.src = src;
254
257
  }));
255
258
  return Promise.allSettled(promises);
256
259
  }
257
260
  function openInNewTab(href, background, additionalProps) {
258
- var _a;
259
261
  try {
260
- (_a = GM.openInTab) == null ? void 0 : _a.call(GM, href, background);
262
+ if (typeof window.GM === "object")
263
+ GM.openInTab(href, background);
261
264
  } catch (e) {
262
265
  const openElem = document.createElement("a");
263
266
  Object.assign(openElem, __spreadValues({
@@ -274,12 +277,17 @@ function openInNewTab(href, background, additionalProps) {
274
277
  });
275
278
  document.body.appendChild(openElem);
276
279
  openElem.click();
277
- setTimeout(openElem.remove, 0);
280
+ setTimeout(() => {
281
+ try {
282
+ openElem.remove();
283
+ } catch (e2) {
284
+ }
285
+ }, 0);
278
286
  }
279
287
  }
280
288
  function interceptEvent(eventObject, eventName, predicate = () => true) {
281
289
  var _a;
282
- if (((_a = GM == null ? undefined : GM.info) == null ? undefined : _a.scriptHandler) && GM.info.scriptHandler === "FireMonkey" && (eventObject === window || eventObject === getUnsafeWindow()))
290
+ if (typeof window.GM === "object" && ((_a = GM == null ? undefined : GM.info) == null ? undefined : _a.scriptHandler) && GM.info.scriptHandler === "FireMonkey" && (eventObject === window || eventObject === getUnsafeWindow()))
283
291
  throw new PlatformError("Intercepting window events is not supported on FireMonkey due to the isolated context the userscript runs in.");
284
292
  Error.stackTraceLimit = Math.max(Error.stackTraceLimit, 100);
285
293
  if (isNaN(Error.stackTraceLimit))
@@ -439,6 +447,8 @@ function computeHash(input, algorithm = "SHA-256") {
439
447
  });
440
448
  }
441
449
  function randomId(length = 16, radix = 16, enhancedEntropy = false, randomCase = true) {
450
+ if (length < 1)
451
+ throw new RangeError("The length argument must be at least 1");
442
452
  if (radix < 2 || radix > 36)
443
453
  throw new RangeError("The radix argument must be between 2 and 36");
444
454
  let arr = [];
@@ -745,14 +755,15 @@ var DataStoreSerializer = class _DataStoreSerializer {
745
755
  });
746
756
  }
747
757
  /**
748
- * Serializes the data stores into a string.
758
+ * Serializes only a subset of the data stores into a string.
759
+ * @param stores An array of store IDs or functions that take a store ID and return a boolean
749
760
  * @param useEncoding Whether to encode the data using each DataStore's `encodeData()` method
750
761
  * @param stringified Whether to return the result as a string or as an array of `SerializedDataStore` objects
751
762
  */
752
- serialize(useEncoding = true, stringified = true) {
763
+ serializePartial(stores, useEncoding = true, stringified = true) {
753
764
  return __async(this, null, function* () {
754
765
  const serData = [];
755
- for (const storeInst of this.stores) {
766
+ for (const storeInst of this.stores.filter((s) => typeof stores === "function" ? stores(s.id) : stores.includes(s.id))) {
756
767
  const data = useEncoding && storeInst.encodingEnabled() ? yield storeInst.encodeData(JSON.stringify(storeInst.getData())) : JSON.stringify(storeInst.getData());
757
768
  serData.push({
758
769
  id: storeInst.id,
@@ -766,15 +777,25 @@ var DataStoreSerializer = class _DataStoreSerializer {
766
777
  });
767
778
  }
768
779
  /**
769
- * Deserializes the data exported via {@linkcode serialize()} and imports it into the DataStore instances.
780
+ * Serializes the data stores into a string.
781
+ * @param useEncoding Whether to encode the data using each DataStore's `encodeData()` method
782
+ * @param stringified Whether to return the result as a string or as an array of `SerializedDataStore` objects
783
+ */
784
+ serialize(useEncoding = true, stringified = true) {
785
+ return __async(this, null, function* () {
786
+ return this.serializePartial(this.stores.map((s) => s.id), useEncoding, stringified);
787
+ });
788
+ }
789
+ /**
790
+ * Deserializes the data exported via {@linkcode serialize()} and imports only a subset into the DataStore instances.
770
791
  * Also triggers the migration process if the data format has changed.
771
792
  */
772
- deserialize(serializedData) {
793
+ deserializePartial(stores, data) {
773
794
  return __async(this, null, function* () {
774
- const deserStores = typeof serializedData === "string" ? JSON.parse(serializedData) : serializedData;
775
- if (!Array.isArray(deserStores) || !deserStores.every(_DataStoreSerializer.isSerializedDataStore))
795
+ const deserStores = typeof data === "string" ? JSON.parse(data) : data;
796
+ if (!Array.isArray(deserStores) || !deserStores.every(_DataStoreSerializer.isSerializedDataStoreObj))
776
797
  throw new TypeError("Invalid serialized data format! Expected an array of SerializedDataStore objects.");
777
- for (const storeData of deserStores) {
798
+ for (const storeData of deserStores.filter((s) => typeof stores === "function" ? stores(s.id) : stores.includes(s.id))) {
778
799
  const storeInst = this.stores.find((s) => s.id === storeData.id);
779
800
  if (!storeInst)
780
801
  throw new Error(`DataStore instance with ID "${storeData.id}" not found! Make sure to provide it in the DataStoreSerializer constructor.`);
@@ -793,44 +814,71 @@ Has: ${checksum}`);
793
814
  }
794
815
  });
795
816
  }
817
+ /**
818
+ * Deserializes the data exported via {@linkcode serialize()} and imports the data into all matching DataStore instances.
819
+ * Also triggers the migration process if the data format has changed.
820
+ */
821
+ deserialize(data) {
822
+ return __async(this, null, function* () {
823
+ return this.deserializePartial(this.stores.map((s) => s.id), data);
824
+ });
825
+ }
796
826
  /**
797
827
  * Loads the persistent data of the DataStore instances into the in-memory cache.
798
828
  * Also triggers the migration process if the data format has changed.
829
+ * @param stores An array of store IDs or a function that takes the store IDs and returns a boolean - if omitted, all stores will be loaded
799
830
  * @returns Returns a PromiseSettledResult array with the results of each DataStore instance in the format `{ id: string, data: object }`
800
831
  */
801
- loadStoresData() {
832
+ loadStoresData(stores) {
802
833
  return __async(this, null, function* () {
803
- return Promise.allSettled(this.stores.map(
804
- (store) => __async(this, null, function* () {
834
+ return Promise.allSettled(
835
+ this.getStoresFiltered(stores).map((store) => __async(this, null, function* () {
805
836
  return {
806
837
  id: store.id,
807
838
  data: yield store.loadData()
808
839
  };
809
- })
810
- ));
840
+ }))
841
+ );
811
842
  });
812
843
  }
813
- /** Resets the persistent data of the DataStore instances to their default values. */
814
- resetStoresData() {
844
+ /**
845
+ * Resets the persistent and in-memory data of the DataStore instances to their default values.
846
+ * @param stores An array of store IDs or a function that takes the store IDs and returns a boolean - if omitted, all stores will be affected
847
+ */
848
+ resetStoresData(stores) {
815
849
  return __async(this, null, function* () {
816
- return Promise.allSettled(this.stores.map((store) => store.saveDefaultData()));
850
+ return Promise.allSettled(
851
+ this.getStoresFiltered(stores).map((store) => store.saveDefaultData())
852
+ );
817
853
  });
818
854
  }
819
855
  /**
820
856
  * Deletes the persistent data of the DataStore instances.
821
- * Leaves the in-memory data untouched.
857
+ * Leaves the in-memory data untouched.
858
+ * @param stores An array of store IDs or a function that takes the store IDs and returns a boolean - if omitted, all stores will be affected
822
859
  */
823
- deleteStoresData() {
860
+ deleteStoresData(stores) {
824
861
  return __async(this, null, function* () {
825
- return Promise.allSettled(this.stores.map((store) => store.deleteData()));
862
+ return Promise.allSettled(
863
+ this.getStoresFiltered(stores).map((store) => store.deleteData())
864
+ );
826
865
  });
827
866
  }
867
+ /** Checks if a given value is an array of SerializedDataStore objects */
868
+ static isSerializedDataStoreObjArray(obj) {
869
+ return Array.isArray(obj) && obj.every((o) => typeof o === "object" && o !== null && "id" in o && "data" in o && "formatVersion" in o && "encoded" in o);
870
+ }
828
871
  /** Checks if a given value is a SerializedDataStore object */
829
- static isSerializedDataStore(obj) {
872
+ static isSerializedDataStoreObj(obj) {
830
873
  return typeof obj === "object" && obj !== null && "id" in obj && "data" in obj && "formatVersion" in obj && "encoded" in obj;
831
874
  }
875
+ /** Returns the DataStore instances whose IDs match the provided array or function */
876
+ getStoresFiltered(stores) {
877
+ return this.stores.filter((s) => typeof stores === "undefined" ? true : Array.isArray(stores) ? stores.includes(s.id) : stores(s.id));
878
+ }
832
879
  };
833
880
  var NanoEmitter = class {
881
+ /** Creates a new instance of NanoEmitter - a lightweight event emitter with helper methods and a strongly typed event map */
834
882
  constructor(options = {}) {
835
883
  __publicField(this, "events", createNanoEvents());
836
884
  __publicField(this, "eventUnsubscribes", []);
@@ -839,7 +887,27 @@ var NanoEmitter = class {
839
887
  publicEmit: false
840
888
  }, options);
841
889
  }
842
- /** Subscribes to an event - returns a function that unsubscribes the event listener */
890
+ /**
891
+ * Subscribes to an event and calls the callback when it's emitted.
892
+ * @param event The event to subscribe to. Use `as "_"` in case your event names aren't thoroughly typed (like when using a template literal, e.g. \`event-${val}\` as "_")
893
+ * @returns Returns a function that can be called to unsubscribe the event listener
894
+ * @example ```ts
895
+ * const emitter = new NanoEmitter<{
896
+ * foo: (bar: string) => void;
897
+ * }>({
898
+ * publicEmit: true,
899
+ * });
900
+ *
901
+ * let i = 0;
902
+ * const unsub = emitter.on("foo", (bar) => {
903
+ * // unsubscribe after 10 events:
904
+ * if(++i === 10) unsub();
905
+ * console.log(bar);
906
+ * });
907
+ *
908
+ * emitter.emit("foo", "bar");
909
+ * ```
910
+ */
843
911
  on(event, cb) {
844
912
  let unsub;
845
913
  const unsubProxy = () => {
@@ -852,19 +920,43 @@ var NanoEmitter = class {
852
920
  this.eventUnsubscribes.push(unsub);
853
921
  return unsubProxy;
854
922
  }
855
- /** Subscribes to an event and calls the callback or resolves the Promise only once */
923
+ /**
924
+ * Subscribes to an event and calls the callback or resolves the Promise only once when it's emitted.
925
+ * @param event The event to subscribe to. Use `as "_"` in case your event names aren't thoroughly typed (like when using a template literal, e.g. \`event-${val}\` as "_")
926
+ * @param cb The callback to call when the event is emitted - if provided or not, the returned Promise will resolve with the event arguments
927
+ * @returns Returns a Promise that resolves with the event arguments when the event is emitted
928
+ * @example ```ts
929
+ * const emitter = new NanoEmitter<{
930
+ * foo: (bar: string) => void;
931
+ * }>();
932
+ *
933
+ * // Promise syntax:
934
+ * const [bar] = await emitter.once("foo");
935
+ * console.log(bar);
936
+ *
937
+ * // Callback syntax:
938
+ * emitter.once("foo", (bar) => console.log(bar));
939
+ * ```
940
+ */
856
941
  once(event, cb) {
857
942
  return new Promise((resolve) => {
858
943
  let unsub;
859
944
  const onceProxy = (...args) => {
860
- unsub();
861
945
  cb == null ? undefined : cb(...args);
946
+ unsub == null ? undefined : unsub();
862
947
  resolve(args);
863
948
  };
864
- unsub = this.on(event, onceProxy);
949
+ unsub = this.events.on(event, onceProxy);
950
+ this.eventUnsubscribes.push(unsub);
865
951
  });
866
952
  }
867
- /** Emits an event on this instance - Needs `publicEmit` to be set to true in the constructor! */
953
+ /**
954
+ * Emits an event on this instance.
955
+ * ⚠️ Needs `publicEmit` to be set to true in the NanoEmitter constructor or super() call!
956
+ * @param event The event to emit
957
+ * @param args The arguments to pass to the event listeners
958
+ * @returns Returns true if `publicEmit` is true and the event was emitted successfully
959
+ */
868
960
  emit(event, ...args) {
869
961
  if (this.emitterOptions.publicEmit) {
870
962
  this.events.emit(event, ...args);
@@ -872,7 +964,7 @@ var NanoEmitter = class {
872
964
  }
873
965
  return false;
874
966
  }
875
- /** Unsubscribes all event listeners */
967
+ /** Unsubscribes all event listeners from this instance */
876
968
  unsubscribeAll() {
877
969
  for (const unsub of this.eventUnsubscribes)
878
970
  unsub();
@@ -912,6 +1004,10 @@ var Debouncer = class extends NanoEmitter {
912
1004
  removeAllListeners() {
913
1005
  this.listeners = [];
914
1006
  }
1007
+ /** Returns all registered listeners */
1008
+ getListeners() {
1009
+ return this.listeners;
1010
+ }
915
1011
  //#region timeout
916
1012
  /** Sets the timeout for the debouncer */
917
1013
  setTimeout(timeout) {
@@ -940,7 +1036,7 @@ var Debouncer = class extends NanoEmitter {
940
1036
  const cl = (...a) => {
941
1037
  this.queuedCall = undefined;
942
1038
  this.emit("call", ...a);
943
- this.listeners.forEach((l) => l.apply(this, a));
1039
+ this.listeners.forEach((l) => l.call(this, ...a));
944
1040
  };
945
1041
  const setRepeatTimeout = () => {
946
1042
  this.activeTimeout = setTimeout(() => {
@@ -1414,8 +1510,6 @@ function autoPlural(term, num, pluralType = "auto") {
1414
1510
  return `${term}${n === 1 ? "" : "s"}`;
1415
1511
  case "-ies":
1416
1512
  return `${String(term).slice(0, -1)}${n === 1 ? "y" : "ies"}`;
1417
- default:
1418
- return String(term);
1419
1513
  }
1420
1514
  }
1421
1515
  function insertValues(input, ...values) {
@@ -1470,6 +1564,115 @@ function consumeStringGen(strGen) {
1470
1564
  function getListLength(obj, zeroOnInvalid = true) {
1471
1565
  return "length" in obj ? obj.length : "size" in obj ? obj.size : "count" in obj ? obj.count : zeroOnInvalid ? 0 : NaN;
1472
1566
  }
1567
+ function purifyObj(obj) {
1568
+ return Object.assign(/* @__PURE__ */ Object.create(null), obj);
1569
+ }
1570
+
1571
+ // lib/Mixins.ts
1572
+ var Mixins = class {
1573
+ /**
1574
+ * Creates a new Mixins instance.
1575
+ * @param config Configuration object to customize the behavior.
1576
+ */
1577
+ constructor(config = {}) {
1578
+ /** List of all registered mixins */
1579
+ __publicField(this, "mixins", []);
1580
+ /** Default configuration object for mixins */
1581
+ __publicField(this, "defaultMixinCfg");
1582
+ /** Whether the priorities should auto-increment if not specified */
1583
+ __publicField(this, "autoIncPrioEnabled");
1584
+ /** The current auto-increment priority counter */
1585
+ __publicField(this, "autoIncPrioCounter", /* @__PURE__ */ new Map());
1586
+ var _a, _b, _c;
1587
+ this.defaultMixinCfg = purifyObj({
1588
+ priority: (_a = config.defaultPriority) != null ? _a : 0,
1589
+ stopPropagation: (_b = config.defaultStopPropagation) != null ? _b : false,
1590
+ signal: config.defaultSignal
1591
+ });
1592
+ this.autoIncPrioEnabled = (_c = config.autoIncrementPriority) != null ? _c : false;
1593
+ }
1594
+ //#region public
1595
+ /**
1596
+ * Adds a mixin function to the given {@linkcode mixinKey}.
1597
+ * If no priority is specified, it will be calculated via the protected method {@linkcode calcPriority()} based on the constructor configuration, or fall back to the default priority.
1598
+ * @param mixinKey The key to identify the mixin function.
1599
+ * @param mixinFn The function to be called to apply the mixin. The first argument is the input value, the second argument is the context object (if any).
1600
+ * @param config Configuration object to customize the mixin behavior, or just the priority if a number is passed.
1601
+ * @returns Returns a cleanup function, to be called when this mixin is no longer needed.
1602
+ */
1603
+ add(mixinKey, mixinFn, config = purifyObj({})) {
1604
+ const calcPrio = typeof config === "number" ? config : this.calcPriority(mixinKey, config);
1605
+ const mixin = purifyObj(__spreadValues(__spreadValues(__spreadProps(__spreadValues({}, this.defaultMixinCfg), {
1606
+ key: mixinKey,
1607
+ fn: mixinFn
1608
+ }), typeof config === "object" ? config : {}), typeof calcPrio === "number" && !isNaN(calcPrio) ? { priority: calcPrio } : {}));
1609
+ this.mixins.push(mixin);
1610
+ const rem = () => {
1611
+ this.mixins = this.mixins.filter((m) => m !== mixin);
1612
+ };
1613
+ if (mixin.signal)
1614
+ mixin.signal.addEventListener("abort", rem, { once: true });
1615
+ return rem;
1616
+ }
1617
+ /** Returns a list of all added mixins with their keys and configuration objects, but not their functions */
1618
+ list() {
1619
+ return this.mixins.map((_a) => {
1620
+ var _b = _a, rest = __objRest(_b, ["fn"]);
1621
+ return rest;
1622
+ });
1623
+ }
1624
+ /**
1625
+ * Applies all mixins with the given key to the input value, respecting the priority and stopPropagation settings.
1626
+ * If additional context is set in the MixinMap, it will need to be passed as the third argument.
1627
+ * @returns The modified value after all mixins have been applied.
1628
+ */
1629
+ resolve(mixinKey, inputValue, ...inputCtx) {
1630
+ const mixins = this.mixins.filter((m) => m.key === mixinKey);
1631
+ const sortedMixins = [...mixins].sort((a, b) => b.priority - a.priority);
1632
+ let result = inputValue;
1633
+ for (let i = 0; i < sortedMixins.length; i++) {
1634
+ const mixin = sortedMixins[i];
1635
+ result = mixin.fn(result, ...inputCtx);
1636
+ if (result instanceof Promise) {
1637
+ return (() => __async(this, null, function* () {
1638
+ result = yield result;
1639
+ if (mixin.stopPropagation)
1640
+ return result;
1641
+ for (let j = i + 1; j < sortedMixins.length; j++) {
1642
+ const mixin2 = sortedMixins[j];
1643
+ result = yield mixin2.fn(result, ...inputCtx);
1644
+ if (mixin2.stopPropagation)
1645
+ break;
1646
+ }
1647
+ return result;
1648
+ }))();
1649
+ } else if (mixin.stopPropagation)
1650
+ break;
1651
+ }
1652
+ return result;
1653
+ }
1654
+ //#region protected
1655
+ /** Calculates the priority for a mixin based on the given configuration and the current auto-increment state of the instance */
1656
+ calcPriority(mixinKey, config) {
1657
+ var _a;
1658
+ if (config.priority !== undefined)
1659
+ return undefined;
1660
+ if (!this.autoIncPrioEnabled)
1661
+ return (_a = config.priority) != null ? _a : this.defaultMixinCfg.priority;
1662
+ if (!this.autoIncPrioCounter.has(mixinKey))
1663
+ this.autoIncPrioCounter.set(mixinKey, this.defaultMixinCfg.priority);
1664
+ let prio = this.autoIncPrioCounter.get(mixinKey);
1665
+ while (this.mixins.some((m) => m.key === mixinKey && m.priority === prio))
1666
+ prio++;
1667
+ this.autoIncPrioCounter.set(mixinKey, prio + 1);
1668
+ return prio;
1669
+ }
1670
+ /** Removes all mixins with the given key */
1671
+ removeAll(mixinKey) {
1672
+ this.mixins.filter((m) => m.key === mixinKey);
1673
+ this.mixins = this.mixins.filter((m) => m.key !== mixinKey);
1674
+ }
1675
+ };
1473
1676
 
1474
1677
  // lib/SelectorObserver.ts
1475
1678
  var SelectorObserver = class {
@@ -1728,15 +1931,15 @@ function getFallbackLanguage() {
1728
1931
  return fallbackLang;
1729
1932
  }
1730
1933
  function addTransform(transform) {
1731
- const [pattern, fn] = transform;
1934
+ const [regex, fn] = transform;
1732
1935
  valTransforms.push({
1733
1936
  fn,
1734
- regex: typeof pattern === "string" ? new RegExp(pattern, "gm") : pattern
1937
+ regex
1735
1938
  });
1736
1939
  }
1737
1940
  function deleteTransform(patternOrFn) {
1738
1941
  const idx = valTransforms.findIndex(
1739
- (t) => typeof patternOrFn === "function" ? t.fn === patternOrFn : typeof patternOrFn === "string" ? t.regex.source === patternOrFn : t.regex === patternOrFn
1942
+ (t) => typeof patternOrFn === "function" ? t.fn === patternOrFn : t.regex === patternOrFn
1740
1943
  );
1741
1944
  if (idx !== -1) {
1742
1945
  valTransforms.splice(idx, 1);
@@ -1807,4 +2010,4 @@ var tr = {
1807
2010
  }
1808
2011
  };
1809
2012
 
1810
- export { ChecksumMismatchError, DataStore, DataStoreSerializer, Debouncer, Dialog, MigrationError, NanoEmitter, PlatformError, SelectorObserver, UUError, addGlobalStyle, addParent, autoPlural, bitSetHas, clamp, compress, computeHash, consumeGen, consumeStringGen, currentDialogId, darkenColor, debounce, decompress, defaultDialogCss, defaultStrings, digitCount, fetchAdvanced, getListLength, getSiblingsFrame, getUnsafeWindow, hexToRgb, insertValues, interceptEvent, interceptWindowEvent, isDomLoaded, isScrollable, lightenColor, mapRange, observeElementProp, onDomLoad, openDialogs, openInNewTab, pauseFor, preloadImages, probeElementStyle, randRange, randomId, randomItem, randomItemIndex, randomizeArray, rgbToHex, roundFixed, setInnerHtmlUnsafe, takeRandomItem, tr };
2013
+ export { ChecksumMismatchError, DataStore, DataStoreSerializer, Debouncer, Dialog, MigrationError, Mixins, NanoEmitter, PlatformError, SelectorObserver, UUError, addGlobalStyle, addParent, autoPlural, bitSetHas, clamp, compress, computeHash, consumeGen, consumeStringGen, currentDialogId, darkenColor, debounce, decompress, defaultDialogCss, defaultStrings, digitCount, fetchAdvanced, getListLength, getSiblingsFrame, getUnsafeWindow, hexToRgb, insertValues, interceptEvent, interceptWindowEvent, isDomLoaded, isScrollable, lightenColor, mapRange, observeElementProp, onDomLoad, openDialogs, openInNewTab, pauseFor, preloadImages, probeElementStyle, purifyObj, randRange, randomId, randomItem, randomItemIndex, randomizeArray, rgbToHex, roundFixed, setInnerHtmlUnsafe, takeRandomItem, tr };
@@ -4,9 +4,9 @@
4
4
  */
5
5
  import type { DataStore } from "./DataStore.js";
6
6
  export type DataStoreSerializerOptions = {
7
- /** Whether to add a checksum to the exported data */
7
+ /** Whether to add a checksum to the exported data. Defaults to `true` */
8
8
  addChecksum?: boolean;
9
- /** Whether to ensure the integrity of the data when importing it (unless the checksum property doesn't exist) */
9
+ /** Whether to ensure the integrity of the data when importing it by throwing an error (doesn't throw when the checksum property doesn't exist). Defaults to `true` */
10
10
  ensureIntegrity?: boolean;
11
11
  };
12
12
  /** Serialized data of a DataStore instance */
@@ -19,7 +19,7 @@ export type SerializedDataStore = {
19
19
  formatVersion: number;
20
20
  /** Whether the data is encoded */
21
21
  encoded: boolean;
22
- /** The checksum of the data - key is not present for data without a checksum */
22
+ /** The checksum of the data - key is not present when `addChecksum` is `false` */
23
23
  checksum?: string;
24
24
  };
25
25
  /** Result of {@linkcode DataStoreSerializer.loadStoresData()} */
@@ -29,6 +29,8 @@ export type LoadStoresDataResult = {
29
29
  /** The in-memory data object */
30
30
  data: object;
31
31
  };
32
+ /** A filter for selecting data stores */
33
+ export type StoreFilter = string[] | ((id: string) => boolean);
32
34
  /**
33
35
  * Allows for easy serialization and deserialization of multiple DataStore instances.
34
36
  *
@@ -43,6 +45,27 @@ export declare class DataStoreSerializer {
43
45
  constructor(stores: DataStore[], options?: DataStoreSerializerOptions);
44
46
  /** Calculates the checksum of a string */
45
47
  protected calcChecksum(input: string): Promise<string>;
48
+ /**
49
+ * Serializes only a subset of the data stores into a string.
50
+ * @param stores An array of store IDs or functions that take a store ID and return a boolean
51
+ * @param useEncoding Whether to encode the data using each DataStore's `encodeData()` method
52
+ * @param stringified Whether to return the result as a string or as an array of `SerializedDataStore` objects
53
+ */
54
+ serializePartial(stores: StoreFilter, useEncoding?: boolean, stringified?: true): Promise<string>;
55
+ /**
56
+ * Serializes only a subset of the data stores into a string.
57
+ * @param stores An array of store IDs or functions that take a store ID and return a boolean
58
+ * @param useEncoding Whether to encode the data using each DataStore's `encodeData()` method
59
+ * @param stringified Whether to return the result as a string or as an array of `SerializedDataStore` objects
60
+ */
61
+ serializePartial(stores: StoreFilter, useEncoding?: boolean, stringified?: false): Promise<SerializedDataStore[]>;
62
+ /**
63
+ * Serializes only a subset of the data stores into a string.
64
+ * @param stores An array of store IDs or functions that take a store ID and return a boolean
65
+ * @param useEncoding Whether to encode the data using each DataStore's `encodeData()` method
66
+ * @param stringified Whether to return the result as a string or as an array of `SerializedDataStore` objects
67
+ */
68
+ serializePartial(stores: StoreFilter, useEncoding?: boolean, stringified?: boolean): Promise<string | SerializedDataStore[]>;
46
69
  /**
47
70
  * Serializes the data stores into a string.
48
71
  * @param useEncoding Whether to encode the data using each DataStore's `encodeData()` method
@@ -56,23 +79,37 @@ export declare class DataStoreSerializer {
56
79
  */
57
80
  serialize(useEncoding?: boolean, stringified?: false): Promise<SerializedDataStore[]>;
58
81
  /**
59
- * Deserializes the data exported via {@linkcode serialize()} and imports it into the DataStore instances.
82
+ * Deserializes the data exported via {@linkcode serialize()} and imports only a subset into the DataStore instances.
83
+ * Also triggers the migration process if the data format has changed.
84
+ */
85
+ deserializePartial(stores: StoreFilter, data: string | SerializedDataStore[]): Promise<void>;
86
+ /**
87
+ * Deserializes the data exported via {@linkcode serialize()} and imports the data into all matching DataStore instances.
60
88
  * Also triggers the migration process if the data format has changed.
61
89
  */
62
- deserialize(serializedData: string | SerializedDataStore[]): Promise<void>;
90
+ deserialize(data: string | SerializedDataStore[]): Promise<void>;
63
91
  /**
64
92
  * Loads the persistent data of the DataStore instances into the in-memory cache.
65
93
  * Also triggers the migration process if the data format has changed.
94
+ * @param stores An array of store IDs or a function that takes the store IDs and returns a boolean - if omitted, all stores will be loaded
66
95
  * @returns Returns a PromiseSettledResult array with the results of each DataStore instance in the format `{ id: string, data: object }`
67
96
  */
68
- loadStoresData(): Promise<PromiseSettledResult<LoadStoresDataResult>[]>;
69
- /** Resets the persistent data of the DataStore instances to their default values. */
70
- resetStoresData(): Promise<PromiseSettledResult<void>[]>;
97
+ loadStoresData(stores?: StoreFilter): Promise<PromiseSettledResult<LoadStoresDataResult>[]>;
98
+ /**
99
+ * Resets the persistent and in-memory data of the DataStore instances to their default values.
100
+ * @param stores An array of store IDs or a function that takes the store IDs and returns a boolean - if omitted, all stores will be affected
101
+ */
102
+ resetStoresData(stores?: StoreFilter): Promise<PromiseSettledResult<void>[]>;
71
103
  /**
72
104
  * Deletes the persistent data of the DataStore instances.
73
105
  * Leaves the in-memory data untouched.
106
+ * @param stores An array of store IDs or a function that takes the store IDs and returns a boolean - if omitted, all stores will be affected
74
107
  */
75
- deleteStoresData(): Promise<PromiseSettledResult<void>[]>;
108
+ deleteStoresData(stores?: StoreFilter): Promise<PromiseSettledResult<void>[]>;
109
+ /** Checks if a given value is an array of SerializedDataStore objects */
110
+ static isSerializedDataStoreObjArray(obj: unknown): obj is SerializedDataStore[];
76
111
  /** Checks if a given value is a SerializedDataStore object */
77
- static isSerializedDataStore(obj: unknown): obj is SerializedDataStore;
112
+ static isSerializedDataStoreObj(obj: unknown): obj is SerializedDataStore;
113
+ /** Returns the DataStore instances whose IDs match the provided array or function */
114
+ protected getStoresFiltered(stores?: StoreFilter): DataStore[];
78
115
  }
@@ -60,6 +60,8 @@ export declare class Debouncer<TFunc extends AnyFunc> extends NanoEmitter<Deboun
60
60
  removeListener(fn: TFunc): void;
61
61
  /** Removes all listeners */
62
62
  removeAllListeners(): void;
63
+ /** Returns all registered listeners */
64
+ getListeners(): TFunc[];
63
65
  /** Sets the timeout for the debouncer */
64
66
  setTimeout(timeout: number): void;
65
67
  /** Returns the current timeout */