@sv443-network/coreutils 3.1.0 → 3.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 +29 -0
- package/dist/CoreUtils.cjs +278 -252
- package/dist/CoreUtils.min.cjs +3 -3
- package/dist/CoreUtils.min.mjs +3 -3
- package/dist/CoreUtils.min.umd.js +3 -3
- package/dist/CoreUtils.mjs +278 -252
- package/dist/CoreUtils.umd.js +773 -631
- package/dist/lib/DataStore.d.ts +38 -4
- package/package.json +5 -5
package/dist/CoreUtils.mjs
CHANGED
|
@@ -463,9 +463,208 @@ function truncStr(input, length, endStr = "...") {
|
|
|
463
463
|
return finalStr.length > length ? finalStr.substring(0, length) : finalStr;
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
+
// node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js
|
|
467
|
+
var createNanoEvents = () => ({
|
|
468
|
+
emit(event, ...args) {
|
|
469
|
+
for (let callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) {
|
|
470
|
+
callbacks[i](...args);
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
events: {},
|
|
474
|
+
on(event, cb) {
|
|
475
|
+
;
|
|
476
|
+
(this.events[event] ||= []).push(cb);
|
|
477
|
+
return () => {
|
|
478
|
+
var _a;
|
|
479
|
+
this.events[event] = (_a = this.events[event]) == null ? void 0 : _a.filter((i) => cb !== i);
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
// lib/NanoEmitter.ts
|
|
485
|
+
var NanoEmitter = class {
|
|
486
|
+
events = createNanoEvents();
|
|
487
|
+
eventUnsubscribes = [];
|
|
488
|
+
emitterOptions;
|
|
489
|
+
/** Creates a new instance of NanoEmitter - a lightweight event emitter with helper methods and a strongly typed event map */
|
|
490
|
+
constructor(options = {}) {
|
|
491
|
+
this.emitterOptions = {
|
|
492
|
+
publicEmit: false,
|
|
493
|
+
...options
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
//#region on
|
|
497
|
+
/**
|
|
498
|
+
* Subscribes to an event and calls the callback when it's emitted.
|
|
499
|
+
* @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 "_")
|
|
500
|
+
* @returns Returns a function that can be called to unsubscribe the event listener
|
|
501
|
+
* @example ```ts
|
|
502
|
+
* const emitter = new NanoEmitter<{
|
|
503
|
+
* foo: (bar: string) => void;
|
|
504
|
+
* }>({
|
|
505
|
+
* publicEmit: true,
|
|
506
|
+
* });
|
|
507
|
+
*
|
|
508
|
+
* let i = 0;
|
|
509
|
+
* const unsub = emitter.on("foo", (bar) => {
|
|
510
|
+
* // unsubscribe after 10 events:
|
|
511
|
+
* if(++i === 10) unsub();
|
|
512
|
+
* console.log(bar);
|
|
513
|
+
* });
|
|
514
|
+
*
|
|
515
|
+
* emitter.emit("foo", "bar");
|
|
516
|
+
* ```
|
|
517
|
+
*/
|
|
518
|
+
on(event, cb) {
|
|
519
|
+
let unsub;
|
|
520
|
+
const unsubProxy = () => {
|
|
521
|
+
if (!unsub)
|
|
522
|
+
return;
|
|
523
|
+
unsub();
|
|
524
|
+
this.eventUnsubscribes = this.eventUnsubscribes.filter((u) => u !== unsub);
|
|
525
|
+
};
|
|
526
|
+
unsub = this.events.on(event, cb);
|
|
527
|
+
this.eventUnsubscribes.push(unsub);
|
|
528
|
+
return unsubProxy;
|
|
529
|
+
}
|
|
530
|
+
//#region once
|
|
531
|
+
/**
|
|
532
|
+
* Subscribes to an event and calls the callback or resolves the Promise only once when it's emitted.
|
|
533
|
+
* @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 "_")
|
|
534
|
+
* @param cb The callback to call when the event is emitted - if provided or not, the returned Promise will resolve with the event arguments
|
|
535
|
+
* @returns Returns a Promise that resolves with the event arguments when the event is emitted
|
|
536
|
+
* @example ```ts
|
|
537
|
+
* const emitter = new NanoEmitter<{
|
|
538
|
+
* foo: (bar: string) => void;
|
|
539
|
+
* }>();
|
|
540
|
+
*
|
|
541
|
+
* // Promise syntax:
|
|
542
|
+
* const [bar] = await emitter.once("foo");
|
|
543
|
+
* console.log(bar);
|
|
544
|
+
*
|
|
545
|
+
* // Callback syntax:
|
|
546
|
+
* emitter.once("foo", (bar) => console.log(bar));
|
|
547
|
+
* ```
|
|
548
|
+
*/
|
|
549
|
+
once(event, cb) {
|
|
550
|
+
return new Promise((resolve) => {
|
|
551
|
+
let unsub;
|
|
552
|
+
const onceProxy = ((...args) => {
|
|
553
|
+
cb == null ? void 0 : cb(...args);
|
|
554
|
+
unsub == null ? void 0 : unsub();
|
|
555
|
+
resolve(args);
|
|
556
|
+
});
|
|
557
|
+
unsub = this.events.on(event, onceProxy);
|
|
558
|
+
this.eventUnsubscribes.push(unsub);
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
//#region onMulti
|
|
562
|
+
/**
|
|
563
|
+
* Allows subscribing to multiple events and calling the callback only when one of, all of, or a subset of the events are emitted, either continuously or only once.
|
|
564
|
+
* @param options An object or array of objects with the following properties:
|
|
565
|
+
* `callback` (required) is the function that will be called when the conditions are met.
|
|
566
|
+
*
|
|
567
|
+
* Set `once` to true to call the callback only once for the first event (or set of events) that match the criteria, then stop listening.
|
|
568
|
+
* If `signal` is provided, the subscription will be canceled when the given signal is aborted.
|
|
569
|
+
*
|
|
570
|
+
* If `oneOf` is used, the callback will be called when any of the matching events are emitted.
|
|
571
|
+
* If `allOf` is used, the callback will be called after all of the matching events are emitted at least once, then any time any of them are emitted.
|
|
572
|
+
* If both `oneOf` and `allOf` are used together, the callback will be called when any of the `oneOf` events are emitted AND all of the `allOf` events have been emitted at least once.
|
|
573
|
+
* At least one of `oneOf` or `allOf` must be provided.
|
|
574
|
+
*
|
|
575
|
+
* @returns Returns a function that can be called to unsubscribe all listeners created by this call. Alternatively, pass an `AbortSignal` to all options objects to achieve the same effect or for finer control.
|
|
576
|
+
*/
|
|
577
|
+
onMulti(options) {
|
|
578
|
+
const allUnsubs = [];
|
|
579
|
+
const unsubAll = () => {
|
|
580
|
+
for (const unsub of allUnsubs)
|
|
581
|
+
unsub();
|
|
582
|
+
allUnsubs.splice(0, allUnsubs.length);
|
|
583
|
+
this.eventUnsubscribes = this.eventUnsubscribes.filter((u) => !allUnsubs.includes(u));
|
|
584
|
+
};
|
|
585
|
+
for (const opts of Array.isArray(options) ? options : [options]) {
|
|
586
|
+
const optsWithDefaults = {
|
|
587
|
+
allOf: [],
|
|
588
|
+
oneOf: [],
|
|
589
|
+
once: false,
|
|
590
|
+
...opts
|
|
591
|
+
};
|
|
592
|
+
const {
|
|
593
|
+
oneOf,
|
|
594
|
+
allOf,
|
|
595
|
+
once,
|
|
596
|
+
signal,
|
|
597
|
+
callback
|
|
598
|
+
} = optsWithDefaults;
|
|
599
|
+
if (signal == null ? void 0 : signal.aborted)
|
|
600
|
+
return unsubAll;
|
|
601
|
+
if (oneOf.length === 0 && allOf.length === 0)
|
|
602
|
+
throw new TypeError("NanoEmitter.onMulti(): Either `oneOf` or `allOf` or both must be provided in the options");
|
|
603
|
+
const curEvtUnsubs = [];
|
|
604
|
+
const checkUnsubAllEvt = (force = false) => {
|
|
605
|
+
if (!(signal == null ? void 0 : signal.aborted) && !force)
|
|
606
|
+
return;
|
|
607
|
+
for (const unsub of curEvtUnsubs)
|
|
608
|
+
unsub();
|
|
609
|
+
curEvtUnsubs.splice(0, curEvtUnsubs.length);
|
|
610
|
+
this.eventUnsubscribes = this.eventUnsubscribes.filter((u) => !curEvtUnsubs.includes(u));
|
|
611
|
+
};
|
|
612
|
+
const allOfEmitted = /* @__PURE__ */ new Set();
|
|
613
|
+
const allOfConditionMet = () => allOf.length === 0 || allOfEmitted.size === allOf.length;
|
|
614
|
+
for (const event of oneOf) {
|
|
615
|
+
const unsub = this.events.on(event, ((...args) => {
|
|
616
|
+
checkUnsubAllEvt();
|
|
617
|
+
if (allOfConditionMet()) {
|
|
618
|
+
callback(event, ...args);
|
|
619
|
+
if (once)
|
|
620
|
+
checkUnsubAllEvt(true);
|
|
621
|
+
}
|
|
622
|
+
}));
|
|
623
|
+
curEvtUnsubs.push(unsub);
|
|
624
|
+
}
|
|
625
|
+
for (const event of allOf) {
|
|
626
|
+
const unsub = this.events.on(event, ((...args) => {
|
|
627
|
+
checkUnsubAllEvt();
|
|
628
|
+
allOfEmitted.add(event);
|
|
629
|
+
if (allOfConditionMet() && (oneOf.length === 0 || oneOf.includes(event))) {
|
|
630
|
+
callback(event, ...args);
|
|
631
|
+
if (once)
|
|
632
|
+
checkUnsubAllEvt(true);
|
|
633
|
+
}
|
|
634
|
+
}));
|
|
635
|
+
curEvtUnsubs.push(unsub);
|
|
636
|
+
}
|
|
637
|
+
allUnsubs.push(() => checkUnsubAllEvt(true));
|
|
638
|
+
}
|
|
639
|
+
return unsubAll;
|
|
640
|
+
}
|
|
641
|
+
//#region emit
|
|
642
|
+
/**
|
|
643
|
+
* Emits an event on this instance.
|
|
644
|
+
* - ⚠️ Needs `publicEmit` to be set to true in the NanoEmitter constructor or super() call!
|
|
645
|
+
* @param event The event to emit
|
|
646
|
+
* @param args The arguments to pass to the event listeners
|
|
647
|
+
* @returns Returns true if `publicEmit` is true and the event was emitted successfully
|
|
648
|
+
*/
|
|
649
|
+
emit(event, ...args) {
|
|
650
|
+
if (this.emitterOptions.publicEmit) {
|
|
651
|
+
this.events.emit(event, ...args);
|
|
652
|
+
return true;
|
|
653
|
+
}
|
|
654
|
+
return false;
|
|
655
|
+
}
|
|
656
|
+
//#region unsubscribeAll
|
|
657
|
+
/** Unsubscribes all event listeners from this instance */
|
|
658
|
+
unsubscribeAll() {
|
|
659
|
+
for (const unsub of this.eventUnsubscribes)
|
|
660
|
+
unsub();
|
|
661
|
+
this.eventUnsubscribes = [];
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
|
|
466
665
|
// lib/DataStore.ts
|
|
467
666
|
var dsFmtVer = 1;
|
|
468
|
-
var DataStore = class {
|
|
667
|
+
var DataStore = class extends NanoEmitter {
|
|
469
668
|
id;
|
|
470
669
|
formatVersion;
|
|
471
670
|
defaultData;
|
|
@@ -474,6 +673,7 @@ var DataStore = class {
|
|
|
474
673
|
compressionFormat = "deflate-raw";
|
|
475
674
|
memoryCache;
|
|
476
675
|
engine;
|
|
676
|
+
keyPrefix;
|
|
477
677
|
options;
|
|
478
678
|
/**
|
|
479
679
|
* Whether all first-init checks should be done.
|
|
@@ -496,6 +696,7 @@ var DataStore = class {
|
|
|
496
696
|
* @param opts The options for this DataStore instance
|
|
497
697
|
*/
|
|
498
698
|
constructor(opts) {
|
|
699
|
+
super(opts.nanoEmitterOptions);
|
|
499
700
|
this.id = opts.id;
|
|
500
701
|
this.formatVersion = opts.formatVersion;
|
|
501
702
|
this.defaultData = opts.defaultData;
|
|
@@ -505,6 +706,7 @@ var DataStore = class {
|
|
|
505
706
|
if (opts.migrateIds)
|
|
506
707
|
this.migrateIds = Array.isArray(opts.migrateIds) ? opts.migrateIds : [opts.migrateIds];
|
|
507
708
|
this.engine = typeof opts.engine === "function" ? opts.engine() : opts.engine;
|
|
709
|
+
this.keyPrefix = opts.keyPrefix ?? "__ds-";
|
|
508
710
|
this.options = opts;
|
|
509
711
|
if ("encodeData" in opts && "decodeData" in opts && Array.isArray(opts.encodeData) && Array.isArray(opts.decodeData)) {
|
|
510
712
|
this.encodeData = [opts.encodeData[0], opts.encodeData[1]];
|
|
@@ -546,13 +748,13 @@ var DataStore = class {
|
|
|
546
748
|
promises.push(this.engine.setValue(newKey, value));
|
|
547
749
|
promises.push(this.engine.deleteValue(oldKey));
|
|
548
750
|
};
|
|
549
|
-
migrateFmt(`_uucfg-${this.id}`,
|
|
751
|
+
migrateFmt(`_uucfg-${this.id}`, `${this.keyPrefix}${this.id}-dat`, oldData);
|
|
550
752
|
if (!isNaN(oldVer))
|
|
551
|
-
migrateFmt(`_uucfgver-${this.id}`,
|
|
753
|
+
migrateFmt(`_uucfgver-${this.id}`, `${this.keyPrefix}${this.id}-ver`, oldVer);
|
|
552
754
|
if (typeof oldEnc === "boolean" || oldEnc === "true" || oldEnc === "false" || typeof oldEnc === "number" || oldEnc === "0" || oldEnc === "1")
|
|
553
|
-
migrateFmt(`_uucfgenc-${this.id}`,
|
|
755
|
+
migrateFmt(`_uucfgenc-${this.id}`, `${this.keyPrefix}${this.id}-enf`, [0, "0", true, "true"].includes(oldEnc) ? this.compressionFormat ?? null : null);
|
|
554
756
|
else {
|
|
555
|
-
promises.push(this.engine.setValue(
|
|
757
|
+
promises.push(this.engine.setValue(`${this.keyPrefix}${this.id}-enf`, this.compressionFormat));
|
|
556
758
|
promises.push(this.engine.deleteValue(`_uucfgenc-${this.id}`));
|
|
557
759
|
}
|
|
558
760
|
await Promise.allSettled(promises);
|
|
@@ -564,31 +766,27 @@ var DataStore = class {
|
|
|
564
766
|
await this.migrateId(this.migrateIds);
|
|
565
767
|
this.migrateIds = [];
|
|
566
768
|
}
|
|
567
|
-
const storedDataRaw = await this.engine.getValue(
|
|
568
|
-
|
|
769
|
+
const storedDataRaw = await this.engine.getValue(`${this.keyPrefix}${this.id}-dat`, null);
|
|
770
|
+
const storedFmtVer = Number(await this.engine.getValue(`${this.keyPrefix}${this.id}-ver`, NaN));
|
|
569
771
|
if (typeof storedDataRaw !== "string" && typeof storedDataRaw !== "object" || storedDataRaw === null || isNaN(storedFmtVer)) {
|
|
570
|
-
await this.saveDefaultData();
|
|
571
|
-
|
|
772
|
+
await this.saveDefaultData(false);
|
|
773
|
+
const data = this.engine.deepCopy(this.defaultData);
|
|
774
|
+
this.events.emit("loadData", data);
|
|
775
|
+
return data;
|
|
572
776
|
}
|
|
573
777
|
const storedData = storedDataRaw ?? JSON.stringify(this.defaultData);
|
|
574
|
-
const encodingFmt = String(await this.engine.getValue(
|
|
778
|
+
const encodingFmt = String(await this.engine.getValue(`${this.keyPrefix}${this.id}-enf`, null));
|
|
575
779
|
const isEncoded = encodingFmt !== "null" && encodingFmt !== "false" && encodingFmt !== "0" && encodingFmt !== "" && encodingFmt !== null;
|
|
576
|
-
let saveData = false;
|
|
577
|
-
if (isNaN(storedFmtVer)) {
|
|
578
|
-
await this.engine.setValue(`__ds-${this.id}-ver`, storedFmtVer = this.formatVersion);
|
|
579
|
-
saveData = true;
|
|
580
|
-
}
|
|
581
780
|
let parsed = typeof storedData === "string" ? await this.engine.deserializeData(storedData, isEncoded) : storedData;
|
|
582
781
|
if (storedFmtVer < this.formatVersion && this.migrations)
|
|
583
782
|
parsed = await this.runMigrations(parsed, storedFmtVer);
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
return this.cachedData = this.engine.deepCopy(parsed);
|
|
588
|
-
else
|
|
589
|
-
return this.engine.deepCopy(parsed);
|
|
783
|
+
const result = this.memoryCache ? this.cachedData = this.engine.deepCopy(parsed) : this.engine.deepCopy(parsed);
|
|
784
|
+
this.events.emit("loadData", result);
|
|
785
|
+
return result;
|
|
590
786
|
} catch (err) {
|
|
787
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
591
788
|
console.warn("Error while parsing JSON data, resetting it to the default value.", err);
|
|
789
|
+
this.events.emit("error", error);
|
|
592
790
|
await this.saveDefaultData();
|
|
593
791
|
return this.defaultData;
|
|
594
792
|
}
|
|
@@ -607,27 +805,47 @@ var DataStore = class {
|
|
|
607
805
|
//#region setData
|
|
608
806
|
/** Saves the data synchronously to the in-memory cache and asynchronously to the persistent storage */
|
|
609
807
|
setData(data) {
|
|
610
|
-
|
|
808
|
+
const dataCopy = this.engine.deepCopy(data);
|
|
809
|
+
if (this.memoryCache) {
|
|
611
810
|
this.cachedData = data;
|
|
811
|
+
this.events.emit("updateDataSync", dataCopy);
|
|
812
|
+
}
|
|
612
813
|
return new Promise(async (resolve) => {
|
|
613
|
-
await Promise.allSettled([
|
|
614
|
-
this.engine.setValue(
|
|
615
|
-
this.engine.setValue(
|
|
616
|
-
this.engine.setValue(
|
|
814
|
+
const results = await Promise.allSettled([
|
|
815
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-dat`, await this.engine.serializeData(data, this.encodingEnabled())),
|
|
816
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-ver`, this.formatVersion),
|
|
817
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-enf`, this.compressionFormat)
|
|
617
818
|
]);
|
|
819
|
+
if (results.every((r) => r.status === "fulfilled"))
|
|
820
|
+
this.events.emit("updateData", dataCopy);
|
|
821
|
+
else {
|
|
822
|
+
const error = new Error("Error while saving data to persistent storage: " + results.map((r) => r.status === "rejected" ? r.reason : null).filter(Boolean).join("; "));
|
|
823
|
+
console.error(error);
|
|
824
|
+
this.events.emit("error", error);
|
|
825
|
+
}
|
|
618
826
|
resolve();
|
|
619
827
|
});
|
|
620
828
|
}
|
|
621
829
|
//#region saveDefaultData
|
|
622
|
-
/**
|
|
623
|
-
|
|
830
|
+
/**
|
|
831
|
+
* Saves the default data passed in the constructor synchronously to the in-memory cache and asynchronously to persistent storage.
|
|
832
|
+
* @param emitEvent Whether to emit the `setDefaultData` event - set to `false` to prevent event emission (used internally during initial population in {@linkcode loadData()})
|
|
833
|
+
*/
|
|
834
|
+
async saveDefaultData(emitEvent = true) {
|
|
624
835
|
if (this.memoryCache)
|
|
625
836
|
this.cachedData = this.defaultData;
|
|
626
|
-
await Promise.allSettled([
|
|
627
|
-
this.engine.setValue(
|
|
628
|
-
this.engine.setValue(
|
|
629
|
-
this.engine.setValue(
|
|
837
|
+
const results = await Promise.allSettled([
|
|
838
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-dat`, await this.engine.serializeData(this.defaultData, this.encodingEnabled())),
|
|
839
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-ver`, this.formatVersion),
|
|
840
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-enf`, this.compressionFormat)
|
|
630
841
|
]);
|
|
842
|
+
if (results.every((r) => r.status === "fulfilled"))
|
|
843
|
+
emitEvent && this.events.emit("setDefaultData", this.defaultData);
|
|
844
|
+
else {
|
|
845
|
+
const error = new Error("Error while saving default data to persistent storage: " + results.map((r) => r.status === "rejected" ? r.reason : null).filter(Boolean).join("; "));
|
|
846
|
+
console.error(error);
|
|
847
|
+
this.events.emit("error", error);
|
|
848
|
+
}
|
|
631
849
|
}
|
|
632
850
|
//#region deleteData
|
|
633
851
|
/**
|
|
@@ -638,11 +856,12 @@ var DataStore = class {
|
|
|
638
856
|
async deleteData() {
|
|
639
857
|
var _a, _b;
|
|
640
858
|
await Promise.allSettled([
|
|
641
|
-
this.engine.deleteValue(
|
|
642
|
-
this.engine.deleteValue(
|
|
643
|
-
this.engine.deleteValue(
|
|
859
|
+
this.engine.deleteValue(`${this.keyPrefix}${this.id}-dat`),
|
|
860
|
+
this.engine.deleteValue(`${this.keyPrefix}${this.id}-ver`),
|
|
861
|
+
this.engine.deleteValue(`${this.keyPrefix}${this.id}-enf`)
|
|
644
862
|
]);
|
|
645
863
|
await ((_b = (_a = this.engine).deleteStorage) == null ? void 0 : _b.call(_a));
|
|
864
|
+
this.events.emit("deleteData");
|
|
646
865
|
}
|
|
647
866
|
//#region encodingEnabled
|
|
648
867
|
/** Returns whether encoding and decoding are enabled for this DataStore instance */
|
|
@@ -663,30 +882,35 @@ var DataStore = class {
|
|
|
663
882
|
let newData = oldData;
|
|
664
883
|
const sortedMigrations = Object.entries(this.migrations).sort(([a], [b]) => Number(a) - Number(b));
|
|
665
884
|
let lastFmtVer = oldFmtVer;
|
|
666
|
-
for (
|
|
885
|
+
for (let i = 0; i < sortedMigrations.length; i++) {
|
|
886
|
+
const [fmtVer, migrationFunc] = sortedMigrations[i];
|
|
667
887
|
const ver = Number(fmtVer);
|
|
668
888
|
if (oldFmtVer < this.formatVersion && oldFmtVer < ver) {
|
|
669
889
|
try {
|
|
670
890
|
const migRes = migrationFunc(newData);
|
|
671
891
|
newData = migRes instanceof Promise ? await migRes : migRes;
|
|
672
892
|
lastFmtVer = oldFmtVer = ver;
|
|
893
|
+
const isFinal = ver >= this.formatVersion || i === sortedMigrations.length - 1;
|
|
894
|
+
this.events.emit("migrateData", ver, newData, isFinal);
|
|
673
895
|
} catch (err) {
|
|
896
|
+
const migError = new MigrationError(`Error while running migration function for format version '${fmtVer}'`, { cause: err });
|
|
897
|
+
this.events.emit("migrationError", ver, migError);
|
|
898
|
+
this.events.emit("error", migError);
|
|
674
899
|
if (!resetOnError)
|
|
675
|
-
throw
|
|
900
|
+
throw migError;
|
|
676
901
|
await this.saveDefaultData();
|
|
677
902
|
return this.engine.deepCopy(this.defaultData);
|
|
678
903
|
}
|
|
679
904
|
}
|
|
680
905
|
}
|
|
681
906
|
await Promise.allSettled([
|
|
682
|
-
this.engine.setValue(
|
|
683
|
-
this.engine.setValue(
|
|
684
|
-
this.engine.setValue(
|
|
907
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-dat`, await this.engine.serializeData(newData, this.encodingEnabled())),
|
|
908
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-ver`, lastFmtVer),
|
|
909
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-enf`, this.compressionFormat)
|
|
685
910
|
]);
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
return this.engine.deepCopy(newData);
|
|
911
|
+
const result = this.memoryCache ? this.cachedData = this.engine.deepCopy(newData) : this.engine.deepCopy(newData);
|
|
912
|
+
this.events.emit("updateData", result);
|
|
913
|
+
return result;
|
|
690
914
|
}
|
|
691
915
|
//#region migrateId
|
|
692
916
|
/**
|
|
@@ -698,9 +922,9 @@ var DataStore = class {
|
|
|
698
922
|
await Promise.all(ids.map(async (id) => {
|
|
699
923
|
const [data, fmtVer, isEncoded] = await (async () => {
|
|
700
924
|
const [d, f, e] = await Promise.all([
|
|
701
|
-
this.engine.getValue(
|
|
702
|
-
this.engine.getValue(
|
|
703
|
-
this.engine.getValue(
|
|
925
|
+
this.engine.getValue(`${this.keyPrefix}${id}-dat`, JSON.stringify(this.defaultData)),
|
|
926
|
+
this.engine.getValue(`${this.keyPrefix}${id}-ver`, NaN),
|
|
927
|
+
this.engine.getValue(`${this.keyPrefix}${id}-enf`, null)
|
|
704
928
|
]);
|
|
705
929
|
return [d, Number(f), Boolean(e) && String(e) !== "null"];
|
|
706
930
|
})();
|
|
@@ -708,13 +932,14 @@ var DataStore = class {
|
|
|
708
932
|
return;
|
|
709
933
|
const parsed = await this.engine.deserializeData(data, isEncoded);
|
|
710
934
|
await Promise.allSettled([
|
|
711
|
-
this.engine.setValue(
|
|
712
|
-
this.engine.setValue(
|
|
713
|
-
this.engine.setValue(
|
|
714
|
-
this.engine.deleteValue(
|
|
715
|
-
this.engine.deleteValue(
|
|
716
|
-
this.engine.deleteValue(
|
|
935
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-dat`, await this.engine.serializeData(parsed, this.encodingEnabled())),
|
|
936
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-ver`, fmtVer),
|
|
937
|
+
this.engine.setValue(`${this.keyPrefix}${this.id}-enf`, this.compressionFormat),
|
|
938
|
+
this.engine.deleteValue(`${this.keyPrefix}${id}-dat`),
|
|
939
|
+
this.engine.deleteValue(`${this.keyPrefix}${id}-ver`),
|
|
940
|
+
this.engine.deleteValue(`${this.keyPrefix}${id}-enf`)
|
|
717
941
|
]);
|
|
942
|
+
this.events.emit("migrateId", id, this.id);
|
|
718
943
|
}));
|
|
719
944
|
}
|
|
720
945
|
};
|
|
@@ -1083,205 +1308,6 @@ Has: ${checksum}`);
|
|
|
1083
1308
|
}
|
|
1084
1309
|
};
|
|
1085
1310
|
|
|
1086
|
-
// node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js
|
|
1087
|
-
var createNanoEvents = () => ({
|
|
1088
|
-
emit(event, ...args) {
|
|
1089
|
-
for (let callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) {
|
|
1090
|
-
callbacks[i](...args);
|
|
1091
|
-
}
|
|
1092
|
-
},
|
|
1093
|
-
events: {},
|
|
1094
|
-
on(event, cb) {
|
|
1095
|
-
;
|
|
1096
|
-
(this.events[event] ||= []).push(cb);
|
|
1097
|
-
return () => {
|
|
1098
|
-
var _a;
|
|
1099
|
-
this.events[event] = (_a = this.events[event]) == null ? void 0 : _a.filter((i) => cb !== i);
|
|
1100
|
-
};
|
|
1101
|
-
}
|
|
1102
|
-
});
|
|
1103
|
-
|
|
1104
|
-
// lib/NanoEmitter.ts
|
|
1105
|
-
var NanoEmitter = class {
|
|
1106
|
-
events = createNanoEvents();
|
|
1107
|
-
eventUnsubscribes = [];
|
|
1108
|
-
emitterOptions;
|
|
1109
|
-
/** Creates a new instance of NanoEmitter - a lightweight event emitter with helper methods and a strongly typed event map */
|
|
1110
|
-
constructor(options = {}) {
|
|
1111
|
-
this.emitterOptions = {
|
|
1112
|
-
publicEmit: false,
|
|
1113
|
-
...options
|
|
1114
|
-
};
|
|
1115
|
-
}
|
|
1116
|
-
//#region on
|
|
1117
|
-
/**
|
|
1118
|
-
* Subscribes to an event and calls the callback when it's emitted.
|
|
1119
|
-
* @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 "_")
|
|
1120
|
-
* @returns Returns a function that can be called to unsubscribe the event listener
|
|
1121
|
-
* @example ```ts
|
|
1122
|
-
* const emitter = new NanoEmitter<{
|
|
1123
|
-
* foo: (bar: string) => void;
|
|
1124
|
-
* }>({
|
|
1125
|
-
* publicEmit: true,
|
|
1126
|
-
* });
|
|
1127
|
-
*
|
|
1128
|
-
* let i = 0;
|
|
1129
|
-
* const unsub = emitter.on("foo", (bar) => {
|
|
1130
|
-
* // unsubscribe after 10 events:
|
|
1131
|
-
* if(++i === 10) unsub();
|
|
1132
|
-
* console.log(bar);
|
|
1133
|
-
* });
|
|
1134
|
-
*
|
|
1135
|
-
* emitter.emit("foo", "bar");
|
|
1136
|
-
* ```
|
|
1137
|
-
*/
|
|
1138
|
-
on(event, cb) {
|
|
1139
|
-
let unsub;
|
|
1140
|
-
const unsubProxy = () => {
|
|
1141
|
-
if (!unsub)
|
|
1142
|
-
return;
|
|
1143
|
-
unsub();
|
|
1144
|
-
this.eventUnsubscribes = this.eventUnsubscribes.filter((u) => u !== unsub);
|
|
1145
|
-
};
|
|
1146
|
-
unsub = this.events.on(event, cb);
|
|
1147
|
-
this.eventUnsubscribes.push(unsub);
|
|
1148
|
-
return unsubProxy;
|
|
1149
|
-
}
|
|
1150
|
-
//#region once
|
|
1151
|
-
/**
|
|
1152
|
-
* Subscribes to an event and calls the callback or resolves the Promise only once when it's emitted.
|
|
1153
|
-
* @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 "_")
|
|
1154
|
-
* @param cb The callback to call when the event is emitted - if provided or not, the returned Promise will resolve with the event arguments
|
|
1155
|
-
* @returns Returns a Promise that resolves with the event arguments when the event is emitted
|
|
1156
|
-
* @example ```ts
|
|
1157
|
-
* const emitter = new NanoEmitter<{
|
|
1158
|
-
* foo: (bar: string) => void;
|
|
1159
|
-
* }>();
|
|
1160
|
-
*
|
|
1161
|
-
* // Promise syntax:
|
|
1162
|
-
* const [bar] = await emitter.once("foo");
|
|
1163
|
-
* console.log(bar);
|
|
1164
|
-
*
|
|
1165
|
-
* // Callback syntax:
|
|
1166
|
-
* emitter.once("foo", (bar) => console.log(bar));
|
|
1167
|
-
* ```
|
|
1168
|
-
*/
|
|
1169
|
-
once(event, cb) {
|
|
1170
|
-
return new Promise((resolve) => {
|
|
1171
|
-
let unsub;
|
|
1172
|
-
const onceProxy = ((...args) => {
|
|
1173
|
-
cb == null ? void 0 : cb(...args);
|
|
1174
|
-
unsub == null ? void 0 : unsub();
|
|
1175
|
-
resolve(args);
|
|
1176
|
-
});
|
|
1177
|
-
unsub = this.events.on(event, onceProxy);
|
|
1178
|
-
this.eventUnsubscribes.push(unsub);
|
|
1179
|
-
});
|
|
1180
|
-
}
|
|
1181
|
-
//#region onMulti
|
|
1182
|
-
/**
|
|
1183
|
-
* Allows subscribing to multiple events and calling the callback only when one of, all of, or a subset of the events are emitted, either continuously or only once.
|
|
1184
|
-
* @param options An object or array of objects with the following properties:
|
|
1185
|
-
* `callback` (required) is the function that will be called when the conditions are met.
|
|
1186
|
-
*
|
|
1187
|
-
* Set `once` to true to call the callback only once for the first event (or set of events) that match the criteria, then stop listening.
|
|
1188
|
-
* If `signal` is provided, the subscription will be canceled when the given signal is aborted.
|
|
1189
|
-
*
|
|
1190
|
-
* If `oneOf` is used, the callback will be called when any of the matching events are emitted.
|
|
1191
|
-
* If `allOf` is used, the callback will be called after all of the matching events are emitted at least once, then any time any of them are emitted.
|
|
1192
|
-
* If both `oneOf` and `allOf` are used together, the callback will be called when any of the `oneOf` events are emitted AND all of the `allOf` events have been emitted at least once.
|
|
1193
|
-
* At least one of `oneOf` or `allOf` must be provided.
|
|
1194
|
-
*
|
|
1195
|
-
* @returns Returns a function that can be called to unsubscribe all listeners created by this call. Alternatively, pass an `AbortSignal` to all options objects to achieve the same effect or for finer control.
|
|
1196
|
-
*/
|
|
1197
|
-
onMulti(options) {
|
|
1198
|
-
const allUnsubs = [];
|
|
1199
|
-
const unsubAll = () => {
|
|
1200
|
-
for (const unsub of allUnsubs)
|
|
1201
|
-
unsub();
|
|
1202
|
-
allUnsubs.splice(0, allUnsubs.length);
|
|
1203
|
-
this.eventUnsubscribes = this.eventUnsubscribes.filter((u) => !allUnsubs.includes(u));
|
|
1204
|
-
};
|
|
1205
|
-
for (const opts of Array.isArray(options) ? options : [options]) {
|
|
1206
|
-
const optsWithDefaults = {
|
|
1207
|
-
allOf: [],
|
|
1208
|
-
oneOf: [],
|
|
1209
|
-
once: false,
|
|
1210
|
-
...opts
|
|
1211
|
-
};
|
|
1212
|
-
const {
|
|
1213
|
-
oneOf,
|
|
1214
|
-
allOf,
|
|
1215
|
-
once,
|
|
1216
|
-
signal,
|
|
1217
|
-
callback
|
|
1218
|
-
} = optsWithDefaults;
|
|
1219
|
-
if (signal == null ? void 0 : signal.aborted)
|
|
1220
|
-
return unsubAll;
|
|
1221
|
-
if (oneOf.length === 0 && allOf.length === 0)
|
|
1222
|
-
throw new TypeError("NanoEmitter.onMulti(): Either `oneOf` or `allOf` or both must be provided in the options");
|
|
1223
|
-
const curEvtUnsubs = [];
|
|
1224
|
-
const checkUnsubAllEvt = (force = false) => {
|
|
1225
|
-
if (!(signal == null ? void 0 : signal.aborted) && !force)
|
|
1226
|
-
return;
|
|
1227
|
-
for (const unsub of curEvtUnsubs)
|
|
1228
|
-
unsub();
|
|
1229
|
-
curEvtUnsubs.splice(0, curEvtUnsubs.length);
|
|
1230
|
-
this.eventUnsubscribes = this.eventUnsubscribes.filter((u) => !curEvtUnsubs.includes(u));
|
|
1231
|
-
};
|
|
1232
|
-
const allOfEmitted = /* @__PURE__ */ new Set();
|
|
1233
|
-
const allOfConditionMet = () => allOf.length === 0 || allOfEmitted.size === allOf.length;
|
|
1234
|
-
for (const event of oneOf) {
|
|
1235
|
-
const unsub = this.events.on(event, ((...args) => {
|
|
1236
|
-
checkUnsubAllEvt();
|
|
1237
|
-
if (allOfConditionMet()) {
|
|
1238
|
-
callback(event, ...args);
|
|
1239
|
-
if (once)
|
|
1240
|
-
checkUnsubAllEvt(true);
|
|
1241
|
-
}
|
|
1242
|
-
}));
|
|
1243
|
-
curEvtUnsubs.push(unsub);
|
|
1244
|
-
}
|
|
1245
|
-
for (const event of allOf) {
|
|
1246
|
-
const unsub = this.events.on(event, ((...args) => {
|
|
1247
|
-
checkUnsubAllEvt();
|
|
1248
|
-
allOfEmitted.add(event);
|
|
1249
|
-
if (allOfConditionMet() && (oneOf.length === 0 || oneOf.includes(event))) {
|
|
1250
|
-
callback(event, ...args);
|
|
1251
|
-
if (once)
|
|
1252
|
-
checkUnsubAllEvt(true);
|
|
1253
|
-
}
|
|
1254
|
-
}));
|
|
1255
|
-
curEvtUnsubs.push(unsub);
|
|
1256
|
-
}
|
|
1257
|
-
allUnsubs.push(() => checkUnsubAllEvt(true));
|
|
1258
|
-
}
|
|
1259
|
-
return unsubAll;
|
|
1260
|
-
}
|
|
1261
|
-
//#region emit
|
|
1262
|
-
/**
|
|
1263
|
-
* Emits an event on this instance.
|
|
1264
|
-
* - ⚠️ Needs `publicEmit` to be set to true in the NanoEmitter constructor or super() call!
|
|
1265
|
-
* @param event The event to emit
|
|
1266
|
-
* @param args The arguments to pass to the event listeners
|
|
1267
|
-
* @returns Returns true if `publicEmit` is true and the event was emitted successfully
|
|
1268
|
-
*/
|
|
1269
|
-
emit(event, ...args) {
|
|
1270
|
-
if (this.emitterOptions.publicEmit) {
|
|
1271
|
-
this.events.emit(event, ...args);
|
|
1272
|
-
return true;
|
|
1273
|
-
}
|
|
1274
|
-
return false;
|
|
1275
|
-
}
|
|
1276
|
-
//#region unsubscribeAll
|
|
1277
|
-
/** Unsubscribes all event listeners from this instance */
|
|
1278
|
-
unsubscribeAll() {
|
|
1279
|
-
for (const unsub of this.eventUnsubscribes)
|
|
1280
|
-
unsub();
|
|
1281
|
-
this.eventUnsubscribes = [];
|
|
1282
|
-
}
|
|
1283
|
-
};
|
|
1284
|
-
|
|
1285
1311
|
// lib/Debouncer.ts
|
|
1286
1312
|
var Debouncer = class extends NanoEmitter {
|
|
1287
1313
|
/**
|