@sv443-network/userutils 6.2.0 → 7.0.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
@@ -79,14 +79,6 @@ function randRange(...args) {
79
79
  throw new TypeError(`Parameter "min" can't be bigger than "max"`);
80
80
  return Math.floor(Math.random() * (max - min + 1)) + min;
81
81
  }
82
- function randomId(length = 16, radix = 16) {
83
- const arr = new Uint8Array(length);
84
- crypto.getRandomValues(arr);
85
- return Array.from(
86
- arr,
87
- (v) => mapRange(v, 0, 255, 0, radix).toString(radix).substring(0, 1)
88
- ).join("");
89
- }
90
82
 
91
83
  // lib/array.ts
92
84
  function randomItem(array) {
@@ -122,28 +114,32 @@ var DataStore = class {
122
114
  * Creates an instance of DataStore to manage a sync & async database that is cached in memory and persistently saved across sessions.
123
115
  * Supports migrating data from older versions to newer ones and populating the cache with default data if no persistent data is found.
124
116
  *
125
- * ⚠️ Requires the directives `@grant GM.getValue` and `@grant GM.setValue`
117
+ * ⚠️ Requires the directives `@grant GM.getValue` and `@grant GM.setValue` if the storageMethod is left as the default of `"GM"`
126
118
  * ⚠️ Make sure to call {@linkcode loadData()} at least once after creating an instance, or the returned data will be the same as `options.defaultData`
127
119
  *
128
- * @template TData The type of the data that is saved in persistent storage (will be automatically inferred from `options.defaultData`) - this should also be the type of the data format associated with the current `options.formatVersion`
120
+ * @template TData The type of the data that is saved in persistent storage for the currently set format version (will be automatically inferred from `defaultData` if not provided) - **This has to be a JSON-compatible object!** (no undefined, circular references, etc.)
129
121
  * @param options The options for this DataStore instance
130
- */
122
+ */
131
123
  constructor(options) {
132
124
  __publicField(this, "id");
133
125
  __publicField(this, "formatVersion");
134
126
  __publicField(this, "defaultData");
135
- __publicField(this, "cachedData");
136
- __publicField(this, "migrations");
137
127
  __publicField(this, "encodeData");
138
128
  __publicField(this, "decodeData");
129
+ __publicField(this, "storageMethod");
130
+ __publicField(this, "cachedData");
131
+ __publicField(this, "migrations");
132
+ var _a;
139
133
  this.id = options.id;
140
134
  this.formatVersion = options.formatVersion;
141
135
  this.defaultData = options.defaultData;
142
136
  this.cachedData = options.defaultData;
143
137
  this.migrations = options.migrations;
138
+ this.storageMethod = (_a = options.storageMethod) != null ? _a : "GM";
144
139
  this.encodeData = options.encodeData;
145
140
  this.decodeData = options.decodeData;
146
141
  }
142
+ //#region public
147
143
  /**
148
144
  * Loads the data saved in persistent storage into the in-memory cache and also returns it.
149
145
  * Automatically populates persistent storage with default data if it doesn't contain any data yet.
@@ -152,19 +148,25 @@ var DataStore = class {
152
148
  loadData() {
153
149
  return __async(this, null, function* () {
154
150
  try {
155
- const gmData = yield GM.getValue(`_uucfg-${this.id}`, this.defaultData);
156
- let gmFmtVer = Number(yield GM.getValue(`_uucfgver-${this.id}`));
151
+ const gmData = yield this.getValue(`_uucfg-${this.id}`, JSON.stringify(this.defaultData));
152
+ let gmFmtVer = Number(yield this.getValue(`_uucfgver-${this.id}`, NaN));
157
153
  if (typeof gmData !== "string") {
158
154
  yield this.saveDefaultData();
159
155
  return __spreadValues({}, this.defaultData);
160
156
  }
161
- const isEncoded = yield GM.getValue(`_uucfgenc-${this.id}`, false);
162
- if (isNaN(gmFmtVer))
163
- yield GM.setValue(`_uucfgver-${this.id}`, gmFmtVer = this.formatVersion);
157
+ const isEncoded = Boolean(yield this.getValue(`_uucfgenc-${this.id}`, false));
158
+ let saveData = false;
159
+ if (isNaN(gmFmtVer)) {
160
+ yield this.setValue(`_uucfgver-${this.id}`, gmFmtVer = this.formatVersion);
161
+ saveData = true;
162
+ }
164
163
  let parsed = yield this.deserializeData(gmData, isEncoded);
165
164
  if (gmFmtVer < this.formatVersion && this.migrations)
166
165
  parsed = yield this.runMigrations(parsed, gmFmtVer);
167
- return __spreadValues({}, this.cachedData = parsed);
166
+ if (saveData)
167
+ yield this.setData(parsed);
168
+ this.cachedData = __spreadValues({}, parsed);
169
+ return this.cachedData;
168
170
  } catch (err) {
169
171
  console.warn("Error while parsing JSON data, resetting it to the default value.", err);
170
172
  yield this.saveDefaultData();
@@ -175,19 +177,20 @@ var DataStore = class {
175
177
  /**
176
178
  * Returns a copy of the data from the in-memory cache.
177
179
  * Use {@linkcode loadData()} to get fresh data from persistent storage (usually not necessary since the cache should always exactly reflect persistent storage).
180
+ * @param deepCopy Whether to return a deep copy of the data (default: `false`) - only necessary if your data object is nested and may have a bigger performance impact if enabled
178
181
  */
179
- getData() {
180
- return this.deepCopy(this.cachedData);
182
+ getData(deepCopy = false) {
183
+ return deepCopy ? this.deepCopy(this.cachedData) : __spreadValues({}, this.cachedData);
181
184
  }
182
185
  /** Saves the data synchronously to the in-memory cache and asynchronously to the persistent storage */
183
186
  setData(data) {
184
187
  this.cachedData = data;
185
- const useEncoding = Boolean(this.encodeData && this.decodeData);
188
+ const useEncoding = this.encodingEnabled();
186
189
  return new Promise((resolve) => __async(this, null, function* () {
187
190
  yield Promise.all([
188
- GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(data, useEncoding)),
189
- GM.setValue(`_uucfgver-${this.id}`, this.formatVersion),
190
- GM.setValue(`_uucfgenc-${this.id}`, useEncoding)
191
+ this.setValue(`_uucfg-${this.id}`, yield this.serializeData(data, useEncoding)),
192
+ this.setValue(`_uucfgver-${this.id}`, this.formatVersion),
193
+ this.setValue(`_uucfgenc-${this.id}`, useEncoding)
191
194
  ]);
192
195
  resolve();
193
196
  }));
@@ -196,12 +199,12 @@ var DataStore = class {
196
199
  saveDefaultData() {
197
200
  return __async(this, null, function* () {
198
201
  this.cachedData = this.defaultData;
199
- const useEncoding = Boolean(this.encodeData && this.decodeData);
202
+ const useEncoding = this.encodingEnabled();
200
203
  return new Promise((resolve) => __async(this, null, function* () {
201
204
  yield Promise.all([
202
- GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(this.defaultData, useEncoding)),
203
- GM.setValue(`_uucfgver-${this.id}`, this.formatVersion),
204
- GM.setValue(`_uucfgenc-${this.id}`, useEncoding)
205
+ this.setValue(`_uucfg-${this.id}`, yield this.serializeData(this.defaultData, useEncoding)),
206
+ this.setValue(`_uucfgver-${this.id}`, this.formatVersion),
207
+ this.setValue(`_uucfgenc-${this.id}`, useEncoding)
205
208
  ]);
206
209
  resolve();
207
210
  }));
@@ -217,14 +220,25 @@ var DataStore = class {
217
220
  deleteData() {
218
221
  return __async(this, null, function* () {
219
222
  yield Promise.all([
220
- GM.deleteValue(`_uucfg-${this.id}`),
221
- GM.deleteValue(`_uucfgver-${this.id}`),
222
- GM.deleteValue(`_uucfgenc-${this.id}`)
223
+ this.deleteValue(`_uucfg-${this.id}`),
224
+ this.deleteValue(`_uucfgver-${this.id}`),
225
+ this.deleteValue(`_uucfgenc-${this.id}`)
223
226
  ]);
224
227
  });
225
228
  }
226
- /** Runs all necessary migration functions consecutively - may be overwritten in a subclass */
227
- runMigrations(oldData, oldFmtVer) {
229
+ /** Returns whether encoding and decoding are enabled for this DataStore instance */
230
+ encodingEnabled() {
231
+ return Boolean(this.encodeData && this.decodeData);
232
+ }
233
+ //#region migrations
234
+ /**
235
+ * Runs all necessary migration functions consecutively and saves the result to the in-memory cache and persistent storage and also returns it.
236
+ * This method is automatically called by {@linkcode loadData()} if the data format has changed since the last time the data was saved.
237
+ * Though calling this method manually is not necessary, it can be useful if you want to run migrations for special occasions like a user importing potentially outdated data that has been previously exported.
238
+ *
239
+ * If one of the migrations fails, the data will be reset to the default value if `resetOnError` is set to `true` (default). Otherwise, an error will be thrown and no data will be saved.
240
+ */
241
+ runMigrations(oldData, oldFmtVer, resetOnError = true) {
228
242
  return __async(this, null, function* () {
229
243
  if (!this.migrations)
230
244
  return oldData;
@@ -239,6 +253,8 @@ var DataStore = class {
239
253
  newData = migRes instanceof Promise ? yield migRes : migRes;
240
254
  lastFmtVer = oldFmtVer = ver;
241
255
  } catch (err) {
256
+ if (!resetOnError)
257
+ throw new Error(`Error while running migration function for format version '${fmtVer}'`);
242
258
  console.error(`Error while running migration function for format version '${fmtVer}' - resetting to the default value.`, err);
243
259
  yield this.saveDefaultData();
244
260
  return this.getData();
@@ -246,18 +262,19 @@ var DataStore = class {
246
262
  }
247
263
  }
248
264
  yield Promise.all([
249
- GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(newData)),
250
- GM.setValue(`_uucfgver-${this.id}`, lastFmtVer),
251
- GM.setValue(`_uucfgenc-${this.id}`, Boolean(this.encodeData && this.decodeData))
265
+ this.setValue(`_uucfg-${this.id}`, yield this.serializeData(newData)),
266
+ this.setValue(`_uucfgver-${this.id}`, lastFmtVer),
267
+ this.setValue(`_uucfgenc-${this.id}`, this.encodingEnabled())
252
268
  ]);
253
- return newData;
269
+ return this.cachedData = __spreadValues({}, newData);
254
270
  });
255
271
  }
272
+ //#region serialization
256
273
  /** Serializes the data using the optional this.encodeData() and returns it as a string */
257
274
  serializeData(data, useEncoding = true) {
258
275
  return __async(this, null, function* () {
259
276
  const stringData = JSON.stringify(data);
260
- if (!this.encodeData || !this.decodeData || !useEncoding)
277
+ if (!this.encodingEnabled() || !useEncoding)
261
278
  return stringData;
262
279
  const encRes = this.encodeData(stringData);
263
280
  if (encRes instanceof Promise)
@@ -268,16 +285,131 @@ var DataStore = class {
268
285
  /** Deserializes the data using the optional this.decodeData() and returns it as a JSON object */
269
286
  deserializeData(data, useEncoding = true) {
270
287
  return __async(this, null, function* () {
271
- let decRes = this.decodeData && this.encodeData && useEncoding ? this.decodeData(data) : void 0;
288
+ let decRes = this.encodingEnabled() && useEncoding ? this.decodeData(data) : void 0;
272
289
  if (decRes instanceof Promise)
273
290
  decRes = yield decRes;
274
291
  return JSON.parse(decRes != null ? decRes : data);
275
292
  });
276
293
  }
277
- /** Copies a JSON-compatible object and loses its internal references */
294
+ //#region misc
295
+ /** Copies a JSON-compatible object and loses all its internal references in the process */
278
296
  deepCopy(obj) {
279
297
  return JSON.parse(JSON.stringify(obj));
280
298
  }
299
+ //#region storage
300
+ /** Gets a value from persistent storage - can be overwritten in a subclass if you want to use something other than GM storage */
301
+ getValue(name, defaultValue) {
302
+ return __async(this, null, function* () {
303
+ var _a, _b;
304
+ switch (this.storageMethod) {
305
+ case "localStorage":
306
+ return (_a = localStorage.getItem(name)) != null ? _a : defaultValue;
307
+ case "sessionStorage":
308
+ return (_b = sessionStorage.getItem(name)) != null ? _b : defaultValue;
309
+ default:
310
+ return GM.getValue(name, defaultValue);
311
+ }
312
+ });
313
+ }
314
+ /**
315
+ * Sets a value in persistent storage - can be overwritten in a subclass if you want to use something other than GM storage.
316
+ * The default storage engines will stringify all passed values like numbers or booleans, so be aware of that.
317
+ */
318
+ setValue(name, value) {
319
+ return __async(this, null, function* () {
320
+ switch (this.storageMethod) {
321
+ case "localStorage":
322
+ return localStorage.setItem(name, String(value));
323
+ case "sessionStorage":
324
+ return sessionStorage.setItem(name, String(value));
325
+ default:
326
+ return GM.setValue(name, String(value));
327
+ }
328
+ });
329
+ }
330
+ /** Deletes a value from persistent storage - can be overwritten in a subclass if you want to use something other than GM storage */
331
+ deleteValue(name) {
332
+ return __async(this, null, function* () {
333
+ switch (this.storageMethod) {
334
+ case "localStorage":
335
+ return localStorage.removeItem(name);
336
+ case "sessionStorage":
337
+ return sessionStorage.removeItem(name);
338
+ default:
339
+ return GM.deleteValue(name);
340
+ }
341
+ });
342
+ }
343
+ };
344
+
345
+ // lib/DataStoreSerializer.ts
346
+ var DataStoreSerializer = class {
347
+ constructor(stores, options = {}) {
348
+ __publicField(this, "stores");
349
+ __publicField(this, "options");
350
+ if (!getUnsafeWindow().crypto || !getUnsafeWindow().crypto.subtle)
351
+ throw new Error("DataStoreSerializer has to run in a secure context (HTTPS)!");
352
+ this.stores = stores;
353
+ this.options = __spreadValues({
354
+ addChecksum: true,
355
+ ensureIntegrity: true
356
+ }, options);
357
+ }
358
+ /** Calculates the checksum of a string */
359
+ calcChecksum(input) {
360
+ return __async(this, null, function* () {
361
+ return computeHash(input, "SHA-256");
362
+ });
363
+ }
364
+ /** Serializes a DataStore instance */
365
+ serializeStore(storeInst) {
366
+ return __async(this, null, function* () {
367
+ const data = storeInst.encodingEnabled() ? yield storeInst.encodeData(JSON.stringify(storeInst.getData())) : JSON.stringify(storeInst.getData());
368
+ const checksum = this.options.addChecksum ? yield this.calcChecksum(data) : void 0;
369
+ return {
370
+ id: storeInst.id,
371
+ data,
372
+ formatVersion: storeInst.formatVersion,
373
+ encoded: storeInst.encodingEnabled(),
374
+ checksum
375
+ };
376
+ });
377
+ }
378
+ /** Serializes the data stores into a string */
379
+ serialize() {
380
+ return __async(this, null, function* () {
381
+ const serData = [];
382
+ for (const store of this.stores)
383
+ serData.push(yield this.serializeStore(store));
384
+ return JSON.stringify(serData);
385
+ });
386
+ }
387
+ /**
388
+ * Deserializes the data exported via {@linkcode serialize()} and imports it into the DataStore instances.
389
+ * Also triggers the migration process if the data format has changed.
390
+ */
391
+ deserialize(serializedData) {
392
+ return __async(this, null, function* () {
393
+ const deserStores = JSON.parse(serializedData);
394
+ for (const storeData of deserStores) {
395
+ const storeInst = this.stores.find((s) => s.id === storeData.id);
396
+ if (!storeInst)
397
+ throw new Error(`DataStore instance with ID "${storeData.id}" not found! Make sure to provide it in the DataStoreSerializer constructor.`);
398
+ if (this.options.ensureIntegrity && typeof storeData.checksum === "string") {
399
+ const checksum = yield this.calcChecksum(storeData.data);
400
+ if (checksum !== storeData.checksum)
401
+ throw new Error(`Checksum mismatch for DataStore with ID "${storeData.id}"!
402
+ Expected: ${storeData.checksum}
403
+ Has: ${checksum}`);
404
+ }
405
+ const decodedData = storeData.encoded && storeInst.encodingEnabled() ? yield storeInst.decodeData(storeData.data) : storeData.data;
406
+ if (storeData.formatVersion && !isNaN(Number(storeData.formatVersion)) && Number(storeData.formatVersion) < storeInst.formatVersion)
407
+ yield storeInst.runMigrations(JSON.parse(decodedData), Number(storeData.formatVersion), false);
408
+ else
409
+ yield storeInst.setData(JSON.parse(decodedData));
410
+ }
411
+ });
412
+ }
281
413
  };
282
414
 
283
415
  // lib/dom.ts
@@ -288,11 +420,6 @@ function getUnsafeWindow() {
288
420
  return window;
289
421
  }
290
422
  }
291
- function insertAfter(beforeElement, afterElement) {
292
- var _a;
293
- (_a = beforeElement.parentNode) == null ? void 0 : _a.insertBefore(afterElement, beforeElement.nextSibling);
294
- return afterElement;
295
- }
296
423
  function addParent(element, newParent) {
297
424
  const oldParent = element.parentNode;
298
425
  if (!oldParent)
@@ -316,18 +443,22 @@ function preloadImages(srcUrls, rejects = false) {
316
443
  }));
317
444
  return Promise.allSettled(promises);
318
445
  }
319
- function openInNewTab(href) {
320
- const openElem = document.createElement("a");
321
- Object.assign(openElem, {
322
- className: "userutils-open-in-new-tab",
323
- target: "_blank",
324
- rel: "noopener noreferrer",
325
- href
326
- });
327
- openElem.style.display = "none";
328
- document.body.appendChild(openElem);
329
- openElem.click();
330
- setTimeout(openElem.remove, 50);
446
+ function openInNewTab(href, background) {
447
+ try {
448
+ GM.openInTab(href, background);
449
+ } catch (e) {
450
+ const openElem = document.createElement("a");
451
+ Object.assign(openElem, {
452
+ className: "userutils-open-in-new-tab",
453
+ target: "_blank",
454
+ rel: "noopener noreferrer",
455
+ href
456
+ });
457
+ openElem.style.display = "none";
458
+ document.body.appendChild(openElem);
459
+ openElem.click();
460
+ setTimeout(openElem.remove, 50);
461
+ }
331
462
  }
332
463
  function interceptEvent(eventObject, eventName, predicate = () => true) {
333
464
  Error.stackTraceLimit = Math.max(Error.stackTraceLimit, 100);
@@ -435,9 +566,14 @@ function fetchAdvanced(_0) {
435
566
  id = setTimeout(() => controller.abort(), timeout);
436
567
  signalOpts = { signal: controller.signal };
437
568
  }
438
- const res = yield fetch(input, __spreadValues(__spreadValues({}, options), signalOpts));
439
- clearTimeout(id);
440
- return res;
569
+ try {
570
+ const res = yield fetch(input, __spreadValues(__spreadValues({}, options), signalOpts));
571
+ id && clearTimeout(id);
572
+ return res;
573
+ } catch (err) {
574
+ id && clearTimeout(id);
575
+ throw err;
576
+ }
441
577
  });
442
578
  }
443
579
  function insertValues(input, ...values) {
@@ -477,8 +613,38 @@ function ab2str(buf) {
477
613
  function str2ab(str) {
478
614
  return Uint8Array.from(getUnsafeWindow().atob(str), (c) => c.charCodeAt(0));
479
615
  }
616
+ function computeHash(input, algorithm = "SHA-256") {
617
+ return __async(this, null, function* () {
618
+ let data;
619
+ if (typeof input === "string") {
620
+ const encoder = new TextEncoder();
621
+ data = encoder.encode(input);
622
+ } else
623
+ data = input;
624
+ const hashBuffer = yield crypto.subtle.digest(algorithm, data);
625
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
626
+ const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
627
+ return hashHex;
628
+ });
629
+ }
630
+ function randomId(length = 16, radix = 16, enhancedEntropy = false) {
631
+ if (enhancedEntropy) {
632
+ const arr = new Uint8Array(length);
633
+ crypto.getRandomValues(arr);
634
+ return Array.from(
635
+ arr,
636
+ (v) => mapRange(v, 0, 255, 0, radix).toString(radix).substring(0, 1)
637
+ ).join("");
638
+ }
639
+ return Array.from(
640
+ { length },
641
+ () => Math.floor(Math.random() * radix).toString(radix)
642
+ ).join("");
643
+ }
480
644
 
481
645
  // lib/SelectorObserver.ts
646
+ var domLoaded = false;
647
+ document.addEventListener("DOMContentLoaded", () => domLoaded = true);
482
648
  var SelectorObserver = class {
483
649
  constructor(baseElement, options = {}) {
484
650
  __publicField(this, "enabled", false);
@@ -489,7 +655,6 @@ var SelectorObserver = class {
489
655
  __publicField(this, "listenerMap");
490
656
  this.baseElement = baseElement;
491
657
  this.listenerMap = /* @__PURE__ */ new Map();
492
- this.observer = new MutationObserver(() => this.checkAllSelectors());
493
658
  const _a = options, {
494
659
  defaultDebounce,
495
660
  defaultDebounceEdge,
@@ -511,11 +676,21 @@ var SelectorObserver = class {
511
676
  disableOnNoListeners: disableOnNoListeners != null ? disableOnNoListeners : false,
512
677
  enableOnAddListener: enableOnAddListener != null ? enableOnAddListener : true
513
678
  };
679
+ if (typeof this.customOptions.checkInterval !== "number") {
680
+ this.observer = new MutationObserver(() => this.checkAllSelectors());
681
+ } else {
682
+ this.checkAllSelectors();
683
+ setInterval(() => this.checkAllSelectors(), this.customOptions.checkInterval);
684
+ }
514
685
  }
686
+ /** Call to check all selectors in the {@linkcode listenerMap} using {@linkcode checkSelector()} */
515
687
  checkAllSelectors() {
688
+ if (!this.enabled || !domLoaded)
689
+ return;
516
690
  for (const [selector, listeners] of this.listenerMap.entries())
517
691
  this.checkSelector(selector, listeners);
518
692
  }
693
+ /** Checks if the element(s) with the given {@linkcode selector} exist in the DOM and calls the respective {@linkcode listeners} accordingly */
519
694
  checkSelector(selector, listeners) {
520
695
  var _a;
521
696
  if (!this.enabled)
@@ -547,9 +722,6 @@ var SelectorObserver = class {
547
722
  this.disable();
548
723
  }
549
724
  }
550
- debounce(func, time, edge = "falling") {
551
- return debounce(func, time, edge);
552
- }
553
725
  /**
554
726
  * Starts observing the children of the base element for changes to the given {@linkcode selector} according to the set {@linkcode options}
555
727
  * @param selector The selector to observe
@@ -558,11 +730,16 @@ var SelectorObserver = class {
558
730
  * @param [options.all] Whether to use `querySelectorAll()` instead - default is false
559
731
  * @param [options.continuous] Whether to call the listener continuously instead of just once - default is false
560
732
  * @param [options.debounce] Whether to debounce the listener to reduce calls to `querySelector` or `querySelectorAll` - set undefined or <=0 to disable (default)
733
+ * @returns Returns a function that can be called to remove this listener more easily
561
734
  */
562
735
  addListener(selector, options) {
563
- options = __spreadValues({ all: false, continuous: false, debounce: 0 }, options);
736
+ options = __spreadValues({
737
+ all: false,
738
+ continuous: false,
739
+ debounce: 0
740
+ }, options);
564
741
  if (options.debounce && options.debounce > 0 || this.customOptions.defaultDebounce && this.customOptions.defaultDebounce > 0) {
565
- options.listener = this.debounce(
742
+ options.listener = debounce(
566
743
  options.listener,
567
744
  options.debounce || this.customOptions.defaultDebounce,
568
745
  options.debounceEdge || this.customOptions.defaultDebounceEdge
@@ -575,13 +752,15 @@ var SelectorObserver = class {
575
752
  if (this.enabled === false && this.customOptions.enableOnAddListener)
576
753
  this.enable();
577
754
  this.checkSelector(selector, [options]);
755
+ return () => this.removeListener(selector, options);
578
756
  }
579
757
  /** Disables the observation of the child elements */
580
758
  disable() {
759
+ var _a;
581
760
  if (!this.enabled)
582
761
  return;
583
762
  this.enabled = false;
584
- this.observer.disconnect();
763
+ (_a = this.observer) == null ? void 0 : _a.disconnect();
585
764
  }
586
765
  /**
587
766
  * Enables or reenables the observation of the child elements.
@@ -589,11 +768,12 @@ var SelectorObserver = class {
589
768
  * @returns Returns true when the observation was enabled, false otherwise (e.g. when the base element wasn't found)
590
769
  */
591
770
  enable(immediatelyCheckSelectors = true) {
771
+ var _a;
592
772
  const baseElement = typeof this.baseElement === "string" ? document.querySelector(this.baseElement) : this.baseElement;
593
773
  if (this.enabled || !baseElement)
594
774
  return false;
595
775
  this.enabled = true;
596
- this.observer.observe(baseElement, this.observerOptions);
776
+ (_a = this.observer) == null ? void 0 : _a.observe(baseElement, this.observerOptions);
597
777
  if (immediatelyCheckSelectors)
598
778
  this.checkAllSelectors();
599
779
  return true;
@@ -664,18 +844,19 @@ tr.getLanguage = () => {
664
844
  };
665
845
 
666
846
  exports.DataStore = DataStore;
847
+ exports.DataStoreSerializer = DataStoreSerializer;
667
848
  exports.SelectorObserver = SelectorObserver;
668
849
  exports.addGlobalStyle = addGlobalStyle;
669
850
  exports.addParent = addParent;
670
851
  exports.autoPlural = autoPlural;
671
852
  exports.clamp = clamp;
672
853
  exports.compress = compress;
854
+ exports.computeHash = computeHash;
673
855
  exports.debounce = debounce;
674
856
  exports.decompress = decompress;
675
857
  exports.fetchAdvanced = fetchAdvanced;
676
858
  exports.getSiblingsFrame = getSiblingsFrame;
677
859
  exports.getUnsafeWindow = getUnsafeWindow;
678
- exports.insertAfter = insertAfter;
679
860
  exports.insertValues = insertValues;
680
861
  exports.interceptEvent = interceptEvent;
681
862
  exports.interceptWindowEvent = interceptWindowEvent;