@sv443-network/coreutils 3.5.1 → 3.6.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 +10 -0
- package/README.md +1 -0
- package/dist/CoreUtils.cjs +70 -28
- package/dist/CoreUtils.min.cjs +4 -4
- package/dist/CoreUtils.min.mjs +4 -4
- package/dist/CoreUtils.min.umd.js +4 -4
- package/dist/CoreUtils.mjs +70 -28
- package/dist/CoreUtils.umd.js +528 -606
- package/dist/lib/DataStoreSerializer.d.ts +13 -8
- package/dist/lib/NanoEmitter.d.ts +16 -1
- package/dist/lib/misc.d.ts +17 -4
- package/dist/lib/types.d.ts +1 -1
- package/package.json +1 -1
package/dist/CoreUtils.mjs
CHANGED
|
@@ -284,12 +284,12 @@ var NetworkError = class extends DatedError {
|
|
|
284
284
|
};
|
|
285
285
|
|
|
286
286
|
// lib/misc.ts
|
|
287
|
-
async function consumeGen(valGen) {
|
|
288
|
-
return await (typeof valGen === "function" ? valGen() : valGen);
|
|
287
|
+
async function consumeGen(valGen, ...args) {
|
|
288
|
+
return await (typeof valGen === "function" ? valGen(...args) : valGen);
|
|
289
289
|
}
|
|
290
|
-
async function consumeStringGen(strGen) {
|
|
290
|
+
async function consumeStringGen(strGen, ...args) {
|
|
291
291
|
return typeof strGen === "string" ? strGen : String(
|
|
292
|
-
typeof strGen === "function" ? await strGen() : strGen
|
|
292
|
+
typeof strGen === "function" ? await strGen(...args) : strGen
|
|
293
293
|
);
|
|
294
294
|
}
|
|
295
295
|
async function fetchAdvanced(input, options = {}) {
|
|
@@ -328,6 +328,17 @@ function pauseFor(time, signal, rejectOnAbort = false) {
|
|
|
328
328
|
function pureObj(obj) {
|
|
329
329
|
return Object.assign(/* @__PURE__ */ Object.create(null), obj ?? {});
|
|
330
330
|
}
|
|
331
|
+
function getterifyObj(obj, asCopy = false) {
|
|
332
|
+
const newObj = {};
|
|
333
|
+
for (const key in obj) {
|
|
334
|
+
Object.defineProperty(newObj, key, {
|
|
335
|
+
get: () => obj[key],
|
|
336
|
+
enumerable: true,
|
|
337
|
+
configurable: true
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
return asCopy ? structuredClone(newObj) : newObj;
|
|
341
|
+
}
|
|
331
342
|
function setImmediateInterval(callback, interval, signal) {
|
|
332
343
|
let intervalId;
|
|
333
344
|
const cleanup = () => clearInterval(intervalId);
|
|
@@ -686,6 +697,8 @@ var NanoEmitter = class {
|
|
|
686
697
|
events = createNanoEvents();
|
|
687
698
|
eventUnsubscribes = [];
|
|
688
699
|
emitterOptions;
|
|
700
|
+
/** Stores the last arguments for each event listed in `catchUpEvents` */
|
|
701
|
+
catchUpMemory = /* @__PURE__ */ new Map();
|
|
689
702
|
/** Creates a new instance of NanoEmitter - a lightweight event emitter with helper methods and a strongly typed event map */
|
|
690
703
|
constructor(options = {}) {
|
|
691
704
|
this.emitterOptions = {
|
|
@@ -693,6 +706,18 @@ var NanoEmitter = class {
|
|
|
693
706
|
...options
|
|
694
707
|
};
|
|
695
708
|
}
|
|
709
|
+
//#region emitEvent
|
|
710
|
+
/**
|
|
711
|
+
* Emits an event on this instance, bypassing the `publicEmit` guard.
|
|
712
|
+
* Prefer this over `this.events.emit()` in subclasses — it updates catch-up memory
|
|
713
|
+
* for any event listed in `catchUpEvents` so late listeners can still receive the last value.
|
|
714
|
+
*/
|
|
715
|
+
emitEvent(event, ...args) {
|
|
716
|
+
var _a;
|
|
717
|
+
if ((_a = this.emitterOptions.catchUpEvents) == null ? void 0 : _a.includes(event))
|
|
718
|
+
this.catchUpMemory.set(event, args);
|
|
719
|
+
this.events.emit(event, ...args);
|
|
720
|
+
}
|
|
696
721
|
//#region on
|
|
697
722
|
/**
|
|
698
723
|
* Subscribes to an event and calls the callback when it's emitted.
|
|
@@ -725,6 +750,9 @@ var NanoEmitter = class {
|
|
|
725
750
|
};
|
|
726
751
|
unsub = this.events.on(event, cb);
|
|
727
752
|
this.eventUnsubscribes.push(unsub);
|
|
753
|
+
const memory = this.catchUpMemory.get(event);
|
|
754
|
+
if (memory)
|
|
755
|
+
cb(...memory);
|
|
728
756
|
return unsubProxy;
|
|
729
757
|
}
|
|
730
758
|
//#region once
|
|
@@ -747,6 +775,12 @@ var NanoEmitter = class {
|
|
|
747
775
|
* ```
|
|
748
776
|
*/
|
|
749
777
|
once(event, cb) {
|
|
778
|
+
const memory = this.catchUpMemory.get(event);
|
|
779
|
+
if (memory) {
|
|
780
|
+
const args = memory;
|
|
781
|
+
cb == null ? void 0 : cb(...args);
|
|
782
|
+
return Promise.resolve(args);
|
|
783
|
+
}
|
|
750
784
|
return new Promise((resolve) => {
|
|
751
785
|
let unsub;
|
|
752
786
|
const onceProxy = ((...args) => {
|
|
@@ -848,7 +882,7 @@ var NanoEmitter = class {
|
|
|
848
882
|
*/
|
|
849
883
|
emit(event, ...args) {
|
|
850
884
|
if (this.emitterOptions.publicEmit) {
|
|
851
|
-
this.
|
|
885
|
+
this.emitEvent(event, ...args);
|
|
852
886
|
return true;
|
|
853
887
|
}
|
|
854
888
|
return false;
|
|
@@ -971,7 +1005,7 @@ var DataStore = class extends NanoEmitter {
|
|
|
971
1005
|
if (typeof storedDataRaw !== "string" && typeof storedDataRaw !== "object" || storedDataRaw === null || isNaN(storedFmtVer)) {
|
|
972
1006
|
await this.saveDefaultData(false);
|
|
973
1007
|
const data = this.engine.deepCopy(this.defaultData);
|
|
974
|
-
this.
|
|
1008
|
+
this.emitEvent("loadData", data);
|
|
975
1009
|
return data;
|
|
976
1010
|
}
|
|
977
1011
|
const storedData = storedDataRaw ?? JSON.stringify(this.defaultData);
|
|
@@ -981,12 +1015,12 @@ var DataStore = class extends NanoEmitter {
|
|
|
981
1015
|
if (storedFmtVer < this.formatVersion && this.migrations)
|
|
982
1016
|
parsed = await this.runMigrations(parsed, storedFmtVer);
|
|
983
1017
|
const result = this.memoryCache ? this.cachedData = this.engine.deepCopy(parsed) : this.engine.deepCopy(parsed);
|
|
984
|
-
this.
|
|
1018
|
+
this.emitEvent("loadData", result);
|
|
985
1019
|
return result;
|
|
986
1020
|
} catch (err) {
|
|
987
1021
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
988
1022
|
console.warn("Error while parsing JSON data, resetting it to the default value.", err);
|
|
989
|
-
this.
|
|
1023
|
+
this.emitEvent("error", error);
|
|
990
1024
|
await this.saveDefaultData();
|
|
991
1025
|
return this.defaultData;
|
|
992
1026
|
}
|
|
@@ -1008,7 +1042,7 @@ var DataStore = class extends NanoEmitter {
|
|
|
1008
1042
|
const dataCopy = this.engine.deepCopy(data);
|
|
1009
1043
|
if (this.memoryCache) {
|
|
1010
1044
|
this.cachedData = data;
|
|
1011
|
-
this.
|
|
1045
|
+
this.emitEvent("updateDataSync", dataCopy);
|
|
1012
1046
|
}
|
|
1013
1047
|
return new Promise(async (resolve) => {
|
|
1014
1048
|
const results = await Promise.allSettled([
|
|
@@ -1017,11 +1051,11 @@ var DataStore = class extends NanoEmitter {
|
|
|
1017
1051
|
this.engine.setValue(`${this.keyPrefix}${this.id}-enf`, this.compressionFormat)
|
|
1018
1052
|
]);
|
|
1019
1053
|
if (results.every((r) => r.status === "fulfilled"))
|
|
1020
|
-
this.
|
|
1054
|
+
this.emitEvent("updateData", dataCopy);
|
|
1021
1055
|
else {
|
|
1022
1056
|
const error = new Error("Error while saving data to persistent storage: " + results.map((r) => r.status === "rejected" ? r.reason : null).filter(Boolean).join("; "));
|
|
1023
1057
|
console.error(error);
|
|
1024
|
-
this.
|
|
1058
|
+
this.emitEvent("error", error);
|
|
1025
1059
|
}
|
|
1026
1060
|
resolve();
|
|
1027
1061
|
});
|
|
@@ -1040,11 +1074,11 @@ var DataStore = class extends NanoEmitter {
|
|
|
1040
1074
|
this.engine.setValue(`${this.keyPrefix}${this.id}-enf`, this.compressionFormat)
|
|
1041
1075
|
]);
|
|
1042
1076
|
if (results.every((r) => r.status === "fulfilled"))
|
|
1043
|
-
emitEvent && this.
|
|
1077
|
+
emitEvent && this.emitEvent("setDefaultData", this.defaultData);
|
|
1044
1078
|
else {
|
|
1045
1079
|
const error = new Error("Error while saving default data to persistent storage: " + results.map((r) => r.status === "rejected" ? r.reason : null).filter(Boolean).join("; "));
|
|
1046
1080
|
console.error(error);
|
|
1047
|
-
this.
|
|
1081
|
+
this.emitEvent("error", error);
|
|
1048
1082
|
}
|
|
1049
1083
|
}
|
|
1050
1084
|
//#region deleteData
|
|
@@ -1061,7 +1095,7 @@ var DataStore = class extends NanoEmitter {
|
|
|
1061
1095
|
this.engine.deleteValue(`${this.keyPrefix}${this.id}-enf`)
|
|
1062
1096
|
]);
|
|
1063
1097
|
await ((_b = (_a = this.engine).deleteStorage) == null ? void 0 : _b.call(_a));
|
|
1064
|
-
this.
|
|
1098
|
+
this.emitEvent("deleteData");
|
|
1065
1099
|
}
|
|
1066
1100
|
//#region encodingEnabled
|
|
1067
1101
|
/** Returns whether encoding and decoding are enabled for this DataStore instance */
|
|
@@ -1091,11 +1125,11 @@ var DataStore = class extends NanoEmitter {
|
|
|
1091
1125
|
newData = migRes instanceof Promise ? await migRes : migRes;
|
|
1092
1126
|
lastFmtVer = oldFmtVer = ver;
|
|
1093
1127
|
const isFinal = ver >= this.formatVersion || i === sortedMigrations.length - 1;
|
|
1094
|
-
this.
|
|
1128
|
+
this.emitEvent("migrateData", ver, newData, isFinal);
|
|
1095
1129
|
} catch (err) {
|
|
1096
1130
|
const migError = new MigrationError(`Error while running migration function for format version '${fmtVer}'`, { cause: err });
|
|
1097
|
-
this.
|
|
1098
|
-
this.
|
|
1131
|
+
this.emitEvent("migrationError", ver, migError);
|
|
1132
|
+
this.emitEvent("error", migError);
|
|
1099
1133
|
if (!resetOnError)
|
|
1100
1134
|
throw migError;
|
|
1101
1135
|
await this.saveDefaultData();
|
|
@@ -1109,7 +1143,7 @@ var DataStore = class extends NanoEmitter {
|
|
|
1109
1143
|
this.engine.setValue(`${this.keyPrefix}${this.id}-enf`, this.compressionFormat)
|
|
1110
1144
|
]);
|
|
1111
1145
|
const result = this.memoryCache ? this.cachedData = this.engine.deepCopy(newData) : this.engine.deepCopy(newData);
|
|
1112
|
-
this.
|
|
1146
|
+
this.emitEvent("updateData", result);
|
|
1113
1147
|
return result;
|
|
1114
1148
|
}
|
|
1115
1149
|
//#region migrateId
|
|
@@ -1139,7 +1173,7 @@ var DataStore = class extends NanoEmitter {
|
|
|
1139
1173
|
this.engine.deleteValue(`${this.keyPrefix}${id}-ver`),
|
|
1140
1174
|
this.engine.deleteValue(`${this.keyPrefix}${id}-enf`)
|
|
1141
1175
|
]);
|
|
1142
|
-
this.
|
|
1176
|
+
this.emitEvent("migrateId", id, this.id);
|
|
1143
1177
|
}));
|
|
1144
1178
|
}
|
|
1145
1179
|
};
|
|
@@ -1382,15 +1416,20 @@ var DataStoreSerializer = class _DataStoreSerializer {
|
|
|
1382
1416
|
addChecksum: true,
|
|
1383
1417
|
ensureIntegrity: true,
|
|
1384
1418
|
remapIds: {},
|
|
1419
|
+
stringifyData: true,
|
|
1385
1420
|
...options
|
|
1386
1421
|
};
|
|
1387
1422
|
}
|
|
1388
1423
|
/**
|
|
1389
|
-
* Calculates the checksum of a string. Uses {@linkcode computeHash()} with SHA-256 and digests as a hex string by default.
|
|
1424
|
+
* Calculates the checksum of a string or {@linkcode DataStoreData} object. Uses {@linkcode computeHash()} with SHA-256 and digests as a hex string by default.
|
|
1390
1425
|
* Override this in a subclass if a custom checksum method is needed.
|
|
1391
1426
|
*/
|
|
1392
1427
|
async calcChecksum(input) {
|
|
1393
|
-
|
|
1428
|
+
try {
|
|
1429
|
+
return computeHash(typeof input === "string" ? input : JSON.stringify(input), "SHA-256");
|
|
1430
|
+
} catch (err) {
|
|
1431
|
+
throw new Error(`Failed to calculate checksum: ${err.message}`, { cause: err });
|
|
1432
|
+
}
|
|
1394
1433
|
}
|
|
1395
1434
|
/**
|
|
1396
1435
|
* Serializes only a subset of the data stores into a string.
|
|
@@ -1405,7 +1444,7 @@ var DataStoreSerializer = class _DataStoreSerializer {
|
|
|
1405
1444
|
for (const storeInst of filteredStores) {
|
|
1406
1445
|
const encoded = Boolean(useEncoding && storeInst.encodingEnabled() && ((_a = storeInst.encodeData) == null ? void 0 : _a[1]));
|
|
1407
1446
|
const rawData = storeInst.memoryCache ? storeInst.getData() : await storeInst.loadData();
|
|
1408
|
-
const data = encoded ? await storeInst.encodeData[1](JSON.stringify(rawData)) : JSON.stringify(rawData);
|
|
1447
|
+
const data = encoded ? await storeInst.encodeData[1](JSON.stringify(rawData)) : this.options.stringifyData ? JSON.stringify(rawData) : rawData;
|
|
1409
1448
|
serData.push({
|
|
1410
1449
|
id: storeInst.id,
|
|
1411
1450
|
data,
|
|
@@ -1451,11 +1490,11 @@ var DataStoreSerializer = class _DataStoreSerializer {
|
|
|
1451
1490
|
Expected: ${storeData.checksum}
|
|
1452
1491
|
Has: ${checksum}`);
|
|
1453
1492
|
}
|
|
1454
|
-
const decodedData = storeData.encoded && storeInst.encodingEnabled() ? await storeInst.decodeData[1](storeData.data) : storeData.data;
|
|
1493
|
+
const decodedData = storeData.encoded && storeInst.encodingEnabled() ? await storeInst.decodeData[1](typeof storeData.data === "string" ? storeData.data : JSON.stringify(storeData.data)) : storeData.data;
|
|
1455
1494
|
if (storeData.formatVersion && !isNaN(Number(storeData.formatVersion)) && Number(storeData.formatVersion) < storeInst.formatVersion)
|
|
1456
|
-
await storeInst.runMigrations(JSON.parse(decodedData), Number(storeData.formatVersion), false);
|
|
1495
|
+
await storeInst.runMigrations(typeof decodedData === "string" ? JSON.parse(decodedData) : decodedData, Number(storeData.formatVersion), false);
|
|
1457
1496
|
else
|
|
1458
|
-
await storeInst.setData(JSON.parse(decodedData));
|
|
1497
|
+
await storeInst.setData(typeof decodedData === "string" ? JSON.parse(decodedData) : decodedData);
|
|
1459
1498
|
}
|
|
1460
1499
|
}
|
|
1461
1500
|
/**
|
|
@@ -1524,6 +1563,8 @@ var Debouncer = class extends NanoEmitter {
|
|
|
1524
1563
|
this.timeout = timeout;
|
|
1525
1564
|
this.type = type;
|
|
1526
1565
|
}
|
|
1566
|
+
timeout;
|
|
1567
|
+
type;
|
|
1527
1568
|
/** All registered listener functions and the time they were attached */
|
|
1528
1569
|
listeners = [];
|
|
1529
1570
|
/** The currently active timeout */
|
|
@@ -1551,7 +1592,7 @@ var Debouncer = class extends NanoEmitter {
|
|
|
1551
1592
|
//#region timeout
|
|
1552
1593
|
/** Sets the timeout for the debouncer */
|
|
1553
1594
|
setTimeout(timeout) {
|
|
1554
|
-
this.
|
|
1595
|
+
this.emitEvent("change", this.timeout = timeout, this.type);
|
|
1555
1596
|
}
|
|
1556
1597
|
/** Returns the current timeout */
|
|
1557
1598
|
getTimeout() {
|
|
@@ -1564,7 +1605,7 @@ var Debouncer = class extends NanoEmitter {
|
|
|
1564
1605
|
//#region type
|
|
1565
1606
|
/** Sets the edge type for the debouncer */
|
|
1566
1607
|
setType(type) {
|
|
1567
|
-
this.
|
|
1608
|
+
this.emitEvent("change", this.timeout, this.type = type);
|
|
1568
1609
|
}
|
|
1569
1610
|
/** Returns the current edge type */
|
|
1570
1611
|
getType() {
|
|
@@ -1575,7 +1616,7 @@ var Debouncer = class extends NanoEmitter {
|
|
|
1575
1616
|
call(...args) {
|
|
1576
1617
|
const cl = (...a) => {
|
|
1577
1618
|
this.queuedCall = void 0;
|
|
1578
|
-
this.
|
|
1619
|
+
this.emitEvent("call", ...a);
|
|
1579
1620
|
this.listeners.forEach((l) => l.call(this, ...a));
|
|
1580
1621
|
};
|
|
1581
1622
|
const setRepeatTimeout = () => {
|
|
@@ -1653,6 +1694,7 @@ export {
|
|
|
1653
1694
|
formatNumber,
|
|
1654
1695
|
getCallStack,
|
|
1655
1696
|
getListLength,
|
|
1697
|
+
getterifyObj,
|
|
1656
1698
|
hexToRgb,
|
|
1657
1699
|
insertValues,
|
|
1658
1700
|
joinArrayReadable,
|