@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/CHANGELOG.md +20 -0
- package/README.md +10 -6
- package/dist/index.cjs +242 -37
- package/dist/index.global.js +243 -38
- package/dist/index.js +241 -38
- package/dist/lib/DataStoreSerializer.d.ts +47 -10
- package/dist/lib/Debouncer.d.ts +2 -0
- package/dist/lib/Mixins.d.ts +127 -0
- package/dist/lib/NanoEmitter.d.ts +52 -5
- package/dist/lib/dom.d.ts +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/misc.d.ts +6 -0
- package/dist/lib/translation.d.ts +1 -1
- package/package.json +18 -6
- package/README-summary.md +0 -213
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
|
-
(
|
|
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(
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
793
|
+
deserializePartial(stores, data) {
|
|
773
794
|
return __async(this, null, function* () {
|
|
774
|
-
const deserStores = typeof
|
|
775
|
-
if (!Array.isArray(deserStores) || !deserStores.every(_DataStoreSerializer.
|
|
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(
|
|
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
|
-
/**
|
|
814
|
-
|
|
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(
|
|
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(
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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.
|
|
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 [
|
|
1934
|
+
const [regex, fn] = transform;
|
|
1732
1935
|
valTransforms.push({
|
|
1733
1936
|
fn,
|
|
1734
|
-
regex
|
|
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 :
|
|
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 (
|
|
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
|
|
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
|
|
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(
|
|
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
|
-
/**
|
|
70
|
-
|
|
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
|
|
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
|
}
|
package/dist/lib/Debouncer.d.ts
CHANGED
|
@@ -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 */
|