@sv443-network/userutils 6.3.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.
@@ -8,7 +8,7 @@
8
8
  // ==UserLibrary==
9
9
  // @name UserUtils
10
10
  // @description Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, create persistent & synchronous data stores, modify the DOM more easily and more
11
- // @version 6.3.0
11
+ // @version 7.0.0
12
12
  // @license MIT
13
13
  // @copyright Sv443 (https://github.com/Sv443)
14
14
 
@@ -99,14 +99,6 @@ var UserUtils = (function (exports) {
99
99
  throw new TypeError(`Parameter "min" can't be bigger than "max"`);
100
100
  return Math.floor(Math.random() * (max - min + 1)) + min;
101
101
  }
102
- function randomId(length = 16, radix = 16) {
103
- const arr = new Uint8Array(length);
104
- crypto.getRandomValues(arr);
105
- return Array.from(
106
- arr,
107
- (v) => mapRange(v, 0, 255, 0, radix).toString(radix).substring(0, 1)
108
- ).join("");
109
- }
110
102
 
111
103
  // lib/array.ts
112
104
  function randomItem(array) {
@@ -142,28 +134,32 @@ var UserUtils = (function (exports) {
142
134
  * Creates an instance of DataStore to manage a sync & async database that is cached in memory and persistently saved across sessions.
143
135
  * Supports migrating data from older versions to newer ones and populating the cache with default data if no persistent data is found.
144
136
  *
145
- * ⚠️ Requires the directives `@grant GM.getValue` and `@grant GM.setValue`
137
+ * ⚠️ Requires the directives `@grant GM.getValue` and `@grant GM.setValue` if the storageMethod is left as the default of `"GM"`
146
138
  * ⚠️ Make sure to call {@linkcode loadData()} at least once after creating an instance, or the returned data will be the same as `options.defaultData`
147
139
  *
148
- * @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`
140
+ * @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.)
149
141
  * @param options The options for this DataStore instance
150
- */
142
+ */
151
143
  constructor(options) {
152
144
  __publicField(this, "id");
153
145
  __publicField(this, "formatVersion");
154
146
  __publicField(this, "defaultData");
155
- __publicField(this, "cachedData");
156
- __publicField(this, "migrations");
157
147
  __publicField(this, "encodeData");
158
148
  __publicField(this, "decodeData");
149
+ __publicField(this, "storageMethod");
150
+ __publicField(this, "cachedData");
151
+ __publicField(this, "migrations");
152
+ var _a;
159
153
  this.id = options.id;
160
154
  this.formatVersion = options.formatVersion;
161
155
  this.defaultData = options.defaultData;
162
156
  this.cachedData = options.defaultData;
163
157
  this.migrations = options.migrations;
158
+ this.storageMethod = (_a = options.storageMethod) != null ? _a : "GM";
164
159
  this.encodeData = options.encodeData;
165
160
  this.decodeData = options.decodeData;
166
161
  }
162
+ //#region public
167
163
  /**
168
164
  * Loads the data saved in persistent storage into the in-memory cache and also returns it.
169
165
  * Automatically populates persistent storage with default data if it doesn't contain any data yet.
@@ -172,19 +168,25 @@ var UserUtils = (function (exports) {
172
168
  loadData() {
173
169
  return __async(this, null, function* () {
174
170
  try {
175
- const gmData = yield GM.getValue(`_uucfg-${this.id}`, this.defaultData);
176
- let gmFmtVer = Number(yield GM.getValue(`_uucfgver-${this.id}`));
171
+ const gmData = yield this.getValue(`_uucfg-${this.id}`, JSON.stringify(this.defaultData));
172
+ let gmFmtVer = Number(yield this.getValue(`_uucfgver-${this.id}`, NaN));
177
173
  if (typeof gmData !== "string") {
178
174
  yield this.saveDefaultData();
179
175
  return __spreadValues({}, this.defaultData);
180
176
  }
181
- const isEncoded = yield GM.getValue(`_uucfgenc-${this.id}`, false);
182
- if (isNaN(gmFmtVer))
183
- yield GM.setValue(`_uucfgver-${this.id}`, gmFmtVer = this.formatVersion);
177
+ const isEncoded = Boolean(yield this.getValue(`_uucfgenc-${this.id}`, false));
178
+ let saveData = false;
179
+ if (isNaN(gmFmtVer)) {
180
+ yield this.setValue(`_uucfgver-${this.id}`, gmFmtVer = this.formatVersion);
181
+ saveData = true;
182
+ }
184
183
  let parsed = yield this.deserializeData(gmData, isEncoded);
185
184
  if (gmFmtVer < this.formatVersion && this.migrations)
186
185
  parsed = yield this.runMigrations(parsed, gmFmtVer);
187
- return __spreadValues({}, this.cachedData = parsed);
186
+ if (saveData)
187
+ yield this.setData(parsed);
188
+ this.cachedData = __spreadValues({}, parsed);
189
+ return this.cachedData;
188
190
  } catch (err) {
189
191
  console.warn("Error while parsing JSON data, resetting it to the default value.", err);
190
192
  yield this.saveDefaultData();
@@ -195,19 +197,20 @@ var UserUtils = (function (exports) {
195
197
  /**
196
198
  * Returns a copy of the data from the in-memory cache.
197
199
  * Use {@linkcode loadData()} to get fresh data from persistent storage (usually not necessary since the cache should always exactly reflect persistent storage).
200
+ * @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
198
201
  */
199
- getData() {
200
- return this.deepCopy(this.cachedData);
202
+ getData(deepCopy = false) {
203
+ return deepCopy ? this.deepCopy(this.cachedData) : __spreadValues({}, this.cachedData);
201
204
  }
202
205
  /** Saves the data synchronously to the in-memory cache and asynchronously to the persistent storage */
203
206
  setData(data) {
204
207
  this.cachedData = data;
205
- const useEncoding = Boolean(this.encodeData && this.decodeData);
208
+ const useEncoding = this.encodingEnabled();
206
209
  return new Promise((resolve) => __async(this, null, function* () {
207
210
  yield Promise.all([
208
- GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(data, useEncoding)),
209
- GM.setValue(`_uucfgver-${this.id}`, this.formatVersion),
210
- GM.setValue(`_uucfgenc-${this.id}`, useEncoding)
211
+ this.setValue(`_uucfg-${this.id}`, yield this.serializeData(data, useEncoding)),
212
+ this.setValue(`_uucfgver-${this.id}`, this.formatVersion),
213
+ this.setValue(`_uucfgenc-${this.id}`, useEncoding)
211
214
  ]);
212
215
  resolve();
213
216
  }));
@@ -216,12 +219,12 @@ var UserUtils = (function (exports) {
216
219
  saveDefaultData() {
217
220
  return __async(this, null, function* () {
218
221
  this.cachedData = this.defaultData;
219
- const useEncoding = Boolean(this.encodeData && this.decodeData);
222
+ const useEncoding = this.encodingEnabled();
220
223
  return new Promise((resolve) => __async(this, null, function* () {
221
224
  yield Promise.all([
222
- GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(this.defaultData, useEncoding)),
223
- GM.setValue(`_uucfgver-${this.id}`, this.formatVersion),
224
- GM.setValue(`_uucfgenc-${this.id}`, useEncoding)
225
+ this.setValue(`_uucfg-${this.id}`, yield this.serializeData(this.defaultData, useEncoding)),
226
+ this.setValue(`_uucfgver-${this.id}`, this.formatVersion),
227
+ this.setValue(`_uucfgenc-${this.id}`, useEncoding)
225
228
  ]);
226
229
  resolve();
227
230
  }));
@@ -237,14 +240,25 @@ var UserUtils = (function (exports) {
237
240
  deleteData() {
238
241
  return __async(this, null, function* () {
239
242
  yield Promise.all([
240
- GM.deleteValue(`_uucfg-${this.id}`),
241
- GM.deleteValue(`_uucfgver-${this.id}`),
242
- GM.deleteValue(`_uucfgenc-${this.id}`)
243
+ this.deleteValue(`_uucfg-${this.id}`),
244
+ this.deleteValue(`_uucfgver-${this.id}`),
245
+ this.deleteValue(`_uucfgenc-${this.id}`)
243
246
  ]);
244
247
  });
245
248
  }
246
- /** Runs all necessary migration functions consecutively - may be overwritten in a subclass */
247
- runMigrations(oldData, oldFmtVer) {
249
+ /** Returns whether encoding and decoding are enabled for this DataStore instance */
250
+ encodingEnabled() {
251
+ return Boolean(this.encodeData && this.decodeData);
252
+ }
253
+ //#region migrations
254
+ /**
255
+ * Runs all necessary migration functions consecutively and saves the result to the in-memory cache and persistent storage and also returns it.
256
+ * This method is automatically called by {@linkcode loadData()} if the data format has changed since the last time the data was saved.
257
+ * 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.
258
+ *
259
+ * 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.
260
+ */
261
+ runMigrations(oldData, oldFmtVer, resetOnError = true) {
248
262
  return __async(this, null, function* () {
249
263
  if (!this.migrations)
250
264
  return oldData;
@@ -259,6 +273,8 @@ var UserUtils = (function (exports) {
259
273
  newData = migRes instanceof Promise ? yield migRes : migRes;
260
274
  lastFmtVer = oldFmtVer = ver;
261
275
  } catch (err) {
276
+ if (!resetOnError)
277
+ throw new Error(`Error while running migration function for format version '${fmtVer}'`);
262
278
  console.error(`Error while running migration function for format version '${fmtVer}' - resetting to the default value.`, err);
263
279
  yield this.saveDefaultData();
264
280
  return this.getData();
@@ -266,18 +282,19 @@ var UserUtils = (function (exports) {
266
282
  }
267
283
  }
268
284
  yield Promise.all([
269
- GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(newData)),
270
- GM.setValue(`_uucfgver-${this.id}`, lastFmtVer),
271
- GM.setValue(`_uucfgenc-${this.id}`, Boolean(this.encodeData && this.decodeData))
285
+ this.setValue(`_uucfg-${this.id}`, yield this.serializeData(newData)),
286
+ this.setValue(`_uucfgver-${this.id}`, lastFmtVer),
287
+ this.setValue(`_uucfgenc-${this.id}`, this.encodingEnabled())
272
288
  ]);
273
- return newData;
289
+ return this.cachedData = __spreadValues({}, newData);
274
290
  });
275
291
  }
292
+ //#region serialization
276
293
  /** Serializes the data using the optional this.encodeData() and returns it as a string */
277
294
  serializeData(data, useEncoding = true) {
278
295
  return __async(this, null, function* () {
279
296
  const stringData = JSON.stringify(data);
280
- if (!this.encodeData || !this.decodeData || !useEncoding)
297
+ if (!this.encodingEnabled() || !useEncoding)
281
298
  return stringData;
282
299
  const encRes = this.encodeData(stringData);
283
300
  if (encRes instanceof Promise)
@@ -288,16 +305,131 @@ var UserUtils = (function (exports) {
288
305
  /** Deserializes the data using the optional this.decodeData() and returns it as a JSON object */
289
306
  deserializeData(data, useEncoding = true) {
290
307
  return __async(this, null, function* () {
291
- let decRes = this.decodeData && this.encodeData && useEncoding ? this.decodeData(data) : void 0;
308
+ let decRes = this.encodingEnabled() && useEncoding ? this.decodeData(data) : void 0;
292
309
  if (decRes instanceof Promise)
293
310
  decRes = yield decRes;
294
311
  return JSON.parse(decRes != null ? decRes : data);
295
312
  });
296
313
  }
297
- /** Copies a JSON-compatible object and loses its internal references */
314
+ //#region misc
315
+ /** Copies a JSON-compatible object and loses all its internal references in the process */
298
316
  deepCopy(obj) {
299
317
  return JSON.parse(JSON.stringify(obj));
300
318
  }
319
+ //#region storage
320
+ /** Gets a value from persistent storage - can be overwritten in a subclass if you want to use something other than GM storage */
321
+ getValue(name, defaultValue) {
322
+ return __async(this, null, function* () {
323
+ var _a, _b;
324
+ switch (this.storageMethod) {
325
+ case "localStorage":
326
+ return (_a = localStorage.getItem(name)) != null ? _a : defaultValue;
327
+ case "sessionStorage":
328
+ return (_b = sessionStorage.getItem(name)) != null ? _b : defaultValue;
329
+ default:
330
+ return GM.getValue(name, defaultValue);
331
+ }
332
+ });
333
+ }
334
+ /**
335
+ * Sets a value in persistent storage - can be overwritten in a subclass if you want to use something other than GM storage.
336
+ * The default storage engines will stringify all passed values like numbers or booleans, so be aware of that.
337
+ */
338
+ setValue(name, value) {
339
+ return __async(this, null, function* () {
340
+ switch (this.storageMethod) {
341
+ case "localStorage":
342
+ return localStorage.setItem(name, String(value));
343
+ case "sessionStorage":
344
+ return sessionStorage.setItem(name, String(value));
345
+ default:
346
+ return GM.setValue(name, String(value));
347
+ }
348
+ });
349
+ }
350
+ /** Deletes a value from persistent storage - can be overwritten in a subclass if you want to use something other than GM storage */
351
+ deleteValue(name) {
352
+ return __async(this, null, function* () {
353
+ switch (this.storageMethod) {
354
+ case "localStorage":
355
+ return localStorage.removeItem(name);
356
+ case "sessionStorage":
357
+ return sessionStorage.removeItem(name);
358
+ default:
359
+ return GM.deleteValue(name);
360
+ }
361
+ });
362
+ }
363
+ };
364
+
365
+ // lib/DataStoreSerializer.ts
366
+ var DataStoreSerializer = class {
367
+ constructor(stores, options = {}) {
368
+ __publicField(this, "stores");
369
+ __publicField(this, "options");
370
+ if (!getUnsafeWindow().crypto || !getUnsafeWindow().crypto.subtle)
371
+ throw new Error("DataStoreSerializer has to run in a secure context (HTTPS)!");
372
+ this.stores = stores;
373
+ this.options = __spreadValues({
374
+ addChecksum: true,
375
+ ensureIntegrity: true
376
+ }, options);
377
+ }
378
+ /** Calculates the checksum of a string */
379
+ calcChecksum(input) {
380
+ return __async(this, null, function* () {
381
+ return computeHash(input, "SHA-256");
382
+ });
383
+ }
384
+ /** Serializes a DataStore instance */
385
+ serializeStore(storeInst) {
386
+ return __async(this, null, function* () {
387
+ const data = storeInst.encodingEnabled() ? yield storeInst.encodeData(JSON.stringify(storeInst.getData())) : JSON.stringify(storeInst.getData());
388
+ const checksum = this.options.addChecksum ? yield this.calcChecksum(data) : void 0;
389
+ return {
390
+ id: storeInst.id,
391
+ data,
392
+ formatVersion: storeInst.formatVersion,
393
+ encoded: storeInst.encodingEnabled(),
394
+ checksum
395
+ };
396
+ });
397
+ }
398
+ /** Serializes the data stores into a string */
399
+ serialize() {
400
+ return __async(this, null, function* () {
401
+ const serData = [];
402
+ for (const store of this.stores)
403
+ serData.push(yield this.serializeStore(store));
404
+ return JSON.stringify(serData);
405
+ });
406
+ }
407
+ /**
408
+ * Deserializes the data exported via {@linkcode serialize()} and imports it into the DataStore instances.
409
+ * Also triggers the migration process if the data format has changed.
410
+ */
411
+ deserialize(serializedData) {
412
+ return __async(this, null, function* () {
413
+ const deserStores = JSON.parse(serializedData);
414
+ for (const storeData of deserStores) {
415
+ const storeInst = this.stores.find((s) => s.id === storeData.id);
416
+ if (!storeInst)
417
+ throw new Error(`DataStore instance with ID "${storeData.id}" not found! Make sure to provide it in the DataStoreSerializer constructor.`);
418
+ if (this.options.ensureIntegrity && typeof storeData.checksum === "string") {
419
+ const checksum = yield this.calcChecksum(storeData.data);
420
+ if (checksum !== storeData.checksum)
421
+ throw new Error(`Checksum mismatch for DataStore with ID "${storeData.id}"!
422
+ Expected: ${storeData.checksum}
423
+ Has: ${checksum}`);
424
+ }
425
+ const decodedData = storeData.encoded && storeInst.encodingEnabled() ? yield storeInst.decodeData(storeData.data) : storeData.data;
426
+ if (storeData.formatVersion && !isNaN(Number(storeData.formatVersion)) && Number(storeData.formatVersion) < storeInst.formatVersion)
427
+ yield storeInst.runMigrations(JSON.parse(decodedData), Number(storeData.formatVersion), false);
428
+ else
429
+ yield storeInst.setData(JSON.parse(decodedData));
430
+ }
431
+ });
432
+ }
301
433
  };
302
434
 
303
435
  // lib/dom.ts
@@ -308,11 +440,6 @@ var UserUtils = (function (exports) {
308
440
  return window;
309
441
  }
310
442
  }
311
- function insertAfter(beforeElement, afterElement) {
312
- var _a;
313
- (_a = beforeElement.parentNode) == null ? void 0 : _a.insertBefore(afterElement, beforeElement.nextSibling);
314
- return afterElement;
315
- }
316
443
  function addParent(element, newParent) {
317
444
  const oldParent = element.parentNode;
318
445
  if (!oldParent)
@@ -459,9 +586,14 @@ var UserUtils = (function (exports) {
459
586
  id = setTimeout(() => controller.abort(), timeout);
460
587
  signalOpts = { signal: controller.signal };
461
588
  }
462
- const res = yield fetch(input, __spreadValues(__spreadValues({}, options), signalOpts));
463
- clearTimeout(id);
464
- return res;
589
+ try {
590
+ const res = yield fetch(input, __spreadValues(__spreadValues({}, options), signalOpts));
591
+ id && clearTimeout(id);
592
+ return res;
593
+ } catch (err) {
594
+ id && clearTimeout(id);
595
+ throw err;
596
+ }
465
597
  });
466
598
  }
467
599
  function insertValues(input, ...values) {
@@ -501,8 +633,38 @@ var UserUtils = (function (exports) {
501
633
  function str2ab(str) {
502
634
  return Uint8Array.from(getUnsafeWindow().atob(str), (c) => c.charCodeAt(0));
503
635
  }
636
+ function computeHash(input, algorithm = "SHA-256") {
637
+ return __async(this, null, function* () {
638
+ let data;
639
+ if (typeof input === "string") {
640
+ const encoder = new TextEncoder();
641
+ data = encoder.encode(input);
642
+ } else
643
+ data = input;
644
+ const hashBuffer = yield crypto.subtle.digest(algorithm, data);
645
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
646
+ const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
647
+ return hashHex;
648
+ });
649
+ }
650
+ function randomId(length = 16, radix = 16, enhancedEntropy = false) {
651
+ if (enhancedEntropy) {
652
+ const arr = new Uint8Array(length);
653
+ crypto.getRandomValues(arr);
654
+ return Array.from(
655
+ arr,
656
+ (v) => mapRange(v, 0, 255, 0, radix).toString(radix).substring(0, 1)
657
+ ).join("");
658
+ }
659
+ return Array.from(
660
+ { length },
661
+ () => Math.floor(Math.random() * radix).toString(radix)
662
+ ).join("");
663
+ }
504
664
 
505
665
  // lib/SelectorObserver.ts
666
+ var domLoaded = false;
667
+ document.addEventListener("DOMContentLoaded", () => domLoaded = true);
506
668
  var SelectorObserver = class {
507
669
  constructor(baseElement, options = {}) {
508
670
  __publicField(this, "enabled", false);
@@ -513,7 +675,6 @@ var UserUtils = (function (exports) {
513
675
  __publicField(this, "listenerMap");
514
676
  this.baseElement = baseElement;
515
677
  this.listenerMap = /* @__PURE__ */ new Map();
516
- this.observer = new MutationObserver(() => this.checkAllSelectors());
517
678
  const _a = options, {
518
679
  defaultDebounce,
519
680
  defaultDebounceEdge,
@@ -535,11 +696,21 @@ var UserUtils = (function (exports) {
535
696
  disableOnNoListeners: disableOnNoListeners != null ? disableOnNoListeners : false,
536
697
  enableOnAddListener: enableOnAddListener != null ? enableOnAddListener : true
537
698
  };
699
+ if (typeof this.customOptions.checkInterval !== "number") {
700
+ this.observer = new MutationObserver(() => this.checkAllSelectors());
701
+ } else {
702
+ this.checkAllSelectors();
703
+ setInterval(() => this.checkAllSelectors(), this.customOptions.checkInterval);
704
+ }
538
705
  }
706
+ /** Call to check all selectors in the {@linkcode listenerMap} using {@linkcode checkSelector()} */
539
707
  checkAllSelectors() {
708
+ if (!this.enabled || !domLoaded)
709
+ return;
540
710
  for (const [selector, listeners] of this.listenerMap.entries())
541
711
  this.checkSelector(selector, listeners);
542
712
  }
713
+ /** Checks if the element(s) with the given {@linkcode selector} exist in the DOM and calls the respective {@linkcode listeners} accordingly */
543
714
  checkSelector(selector, listeners) {
544
715
  var _a;
545
716
  if (!this.enabled)
@@ -571,9 +742,6 @@ var UserUtils = (function (exports) {
571
742
  this.disable();
572
743
  }
573
744
  }
574
- debounce(func, time, edge = "falling") {
575
- return debounce(func, time, edge);
576
- }
577
745
  /**
578
746
  * Starts observing the children of the base element for changes to the given {@linkcode selector} according to the set {@linkcode options}
579
747
  * @param selector The selector to observe
@@ -582,11 +750,16 @@ var UserUtils = (function (exports) {
582
750
  * @param [options.all] Whether to use `querySelectorAll()` instead - default is false
583
751
  * @param [options.continuous] Whether to call the listener continuously instead of just once - default is false
584
752
  * @param [options.debounce] Whether to debounce the listener to reduce calls to `querySelector` or `querySelectorAll` - set undefined or <=0 to disable (default)
753
+ * @returns Returns a function that can be called to remove this listener more easily
585
754
  */
586
755
  addListener(selector, options) {
587
- options = __spreadValues({ all: false, continuous: false, debounce: 0 }, options);
756
+ options = __spreadValues({
757
+ all: false,
758
+ continuous: false,
759
+ debounce: 0
760
+ }, options);
588
761
  if (options.debounce && options.debounce > 0 || this.customOptions.defaultDebounce && this.customOptions.defaultDebounce > 0) {
589
- options.listener = this.debounce(
762
+ options.listener = debounce(
590
763
  options.listener,
591
764
  options.debounce || this.customOptions.defaultDebounce,
592
765
  options.debounceEdge || this.customOptions.defaultDebounceEdge
@@ -599,13 +772,15 @@ var UserUtils = (function (exports) {
599
772
  if (this.enabled === false && this.customOptions.enableOnAddListener)
600
773
  this.enable();
601
774
  this.checkSelector(selector, [options]);
775
+ return () => this.removeListener(selector, options);
602
776
  }
603
777
  /** Disables the observation of the child elements */
604
778
  disable() {
779
+ var _a;
605
780
  if (!this.enabled)
606
781
  return;
607
782
  this.enabled = false;
608
- this.observer.disconnect();
783
+ (_a = this.observer) == null ? void 0 : _a.disconnect();
609
784
  }
610
785
  /**
611
786
  * Enables or reenables the observation of the child elements.
@@ -613,11 +788,12 @@ var UserUtils = (function (exports) {
613
788
  * @returns Returns true when the observation was enabled, false otherwise (e.g. when the base element wasn't found)
614
789
  */
615
790
  enable(immediatelyCheckSelectors = true) {
791
+ var _a;
616
792
  const baseElement = typeof this.baseElement === "string" ? document.querySelector(this.baseElement) : this.baseElement;
617
793
  if (this.enabled || !baseElement)
618
794
  return false;
619
795
  this.enabled = true;
620
- this.observer.observe(baseElement, this.observerOptions);
796
+ (_a = this.observer) == null ? void 0 : _a.observe(baseElement, this.observerOptions);
621
797
  if (immediatelyCheckSelectors)
622
798
  this.checkAllSelectors();
623
799
  return true;
@@ -688,18 +864,19 @@ var UserUtils = (function (exports) {
688
864
  };
689
865
 
690
866
  exports.DataStore = DataStore;
867
+ exports.DataStoreSerializer = DataStoreSerializer;
691
868
  exports.SelectorObserver = SelectorObserver;
692
869
  exports.addGlobalStyle = addGlobalStyle;
693
870
  exports.addParent = addParent;
694
871
  exports.autoPlural = autoPlural;
695
872
  exports.clamp = clamp;
696
873
  exports.compress = compress;
874
+ exports.computeHash = computeHash;
697
875
  exports.debounce = debounce;
698
876
  exports.decompress = decompress;
699
877
  exports.fetchAdvanced = fetchAdvanced;
700
878
  exports.getSiblingsFrame = getSiblingsFrame;
701
879
  exports.getUnsafeWindow = getUnsafeWindow;
702
- exports.insertAfter = insertAfter;
703
880
  exports.insertValues = insertValues;
704
881
  exports.interceptEvent = interceptEvent;
705
882
  exports.interceptWindowEvent = interceptWindowEvent;