@converse/skeletor 3.0.1 → 3.1.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/skeletor.js CHANGED
@@ -5,7 +5,7 @@
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
7
  /** Used for built-in method references. */
8
- var objectProto$l = Object.prototype;
8
+ var objectProto$m = Object.prototype;
9
9
 
10
10
  /**
11
11
  * Checks if `value` is likely a prototype object.
@@ -16,7 +16,7 @@
16
16
  */
17
17
  function isPrototype(value) {
18
18
  var Ctor = value && value.constructor,
19
- proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$l;
19
+ proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$m;
20
20
 
21
21
  return value === proto;
22
22
  }
@@ -39,10 +39,10 @@
39
39
  var nativeKeys = overArg(Object.keys, Object);
40
40
 
41
41
  /** Used for built-in method references. */
42
- var objectProto$k = Object.prototype;
42
+ var objectProto$l = Object.prototype;
43
43
 
44
44
  /** Used to check objects for own properties. */
45
- var hasOwnProperty$h = objectProto$k.hasOwnProperty;
45
+ var hasOwnProperty$i = objectProto$l.hasOwnProperty;
46
46
 
47
47
  /**
48
48
  * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
@@ -57,7 +57,7 @@
57
57
  }
58
58
  var result = [];
59
59
  for (var key in Object(object)) {
60
- if (hasOwnProperty$h.call(object, key) && key != 'constructor') {
60
+ if (hasOwnProperty$i.call(object, key) && key != 'constructor') {
61
61
  result.push(key);
62
62
  }
63
63
  }
@@ -77,17 +77,17 @@
77
77
  var Symbol$1 = root$1.Symbol;
78
78
 
79
79
  /** Used for built-in method references. */
80
- var objectProto$j = Object.prototype;
80
+ var objectProto$k = Object.prototype;
81
81
 
82
82
  /** Used to check objects for own properties. */
83
- var hasOwnProperty$g = objectProto$j.hasOwnProperty;
83
+ var hasOwnProperty$h = objectProto$k.hasOwnProperty;
84
84
 
85
85
  /**
86
86
  * Used to resolve the
87
87
  * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
88
88
  * of values.
89
89
  */
90
- var nativeObjectToString$2 = objectProto$j.toString;
90
+ var nativeObjectToString$2 = objectProto$k.toString;
91
91
 
92
92
  /** Built-in value references. */
93
93
  var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined;
@@ -100,7 +100,7 @@
100
100
  * @returns {string} Returns the raw `toStringTag`.
101
101
  */
102
102
  function getRawTag(value) {
103
- var isOwn = hasOwnProperty$g.call(value, symToStringTag$1),
103
+ var isOwn = hasOwnProperty$h.call(value, symToStringTag$1),
104
104
  tag = value[symToStringTag$1];
105
105
 
106
106
  try {
@@ -120,14 +120,14 @@
120
120
  }
121
121
 
122
122
  /** Used for built-in method references. */
123
- var objectProto$i = Object.prototype;
123
+ var objectProto$j = Object.prototype;
124
124
 
125
125
  /**
126
126
  * Used to resolve the
127
127
  * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
128
128
  * of values.
129
129
  */
130
- var nativeObjectToString$1 = objectProto$i.toString;
130
+ var nativeObjectToString$1 = objectProto$j.toString;
131
131
 
132
132
  /**
133
133
  * Converts `value` to a string using `Object.prototype.toString`.
@@ -282,17 +282,17 @@
282
282
 
283
283
  /** Used for built-in method references. */
284
284
  var funcProto$1 = Function.prototype,
285
- objectProto$h = Object.prototype;
285
+ objectProto$i = Object.prototype;
286
286
 
287
287
  /** Used to resolve the decompiled source of functions. */
288
288
  var funcToString$1 = funcProto$1.toString;
289
289
 
290
290
  /** Used to check objects for own properties. */
291
- var hasOwnProperty$f = objectProto$h.hasOwnProperty;
291
+ var hasOwnProperty$g = objectProto$i.hasOwnProperty;
292
292
 
293
293
  /** Used to detect if a method is native. */
294
294
  var reIsNative = RegExp('^' +
295
- funcToString$1.call(hasOwnProperty$f).replace(reRegExpChar, '\\$&')
295
+ funcToString$1.call(hasOwnProperty$g).replace(reRegExpChar, '\\$&')
296
296
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
297
297
  );
298
298
 
@@ -341,16 +341,16 @@
341
341
  var DataView = getNative(root$1, 'DataView');
342
342
 
343
343
  /* Built-in method references that are verified to be native. */
344
- var Map = getNative(root$1, 'Map');
344
+ var Map$1 = getNative(root$1, 'Map');
345
345
 
346
346
  /* Built-in method references that are verified to be native. */
347
347
  var Promise$1 = getNative(root$1, 'Promise');
348
348
 
349
349
  /* Built-in method references that are verified to be native. */
350
- var Set = getNative(root$1, 'Set');
350
+ var Set$1 = getNative(root$1, 'Set');
351
351
 
352
352
  /* Built-in method references that are verified to be native. */
353
- var WeakMap = getNative(root$1, 'WeakMap');
353
+ var WeakMap$1 = getNative(root$1, 'WeakMap');
354
354
 
355
355
  /** `Object#toString` result references. */
356
356
  var mapTag$6 = '[object Map]',
@@ -363,10 +363,10 @@
363
363
 
364
364
  /** Used to detect maps, sets, and weakmaps. */
365
365
  var dataViewCtorString = toSource(DataView),
366
- mapCtorString = toSource(Map),
366
+ mapCtorString = toSource(Map$1),
367
367
  promiseCtorString = toSource(Promise$1),
368
- setCtorString = toSource(Set),
369
- weakMapCtorString = toSource(WeakMap);
368
+ setCtorString = toSource(Set$1),
369
+ weakMapCtorString = toSource(WeakMap$1);
370
370
 
371
371
  /**
372
372
  * Gets the `toStringTag` of `value`.
@@ -379,10 +379,10 @@
379
379
 
380
380
  // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
381
381
  if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag$4) ||
382
- (Map && getTag(new Map) != mapTag$6) ||
382
+ (Map$1 && getTag(new Map$1) != mapTag$6) ||
383
383
  (Promise$1 && getTag(Promise$1.resolve()) != promiseTag) ||
384
- (Set && getTag(new Set) != setTag$6) ||
385
- (WeakMap && getTag(new WeakMap) != weakMapTag$2)) {
384
+ (Set$1 && getTag(new Set$1) != setTag$6) ||
385
+ (WeakMap$1 && getTag(new WeakMap$1) != weakMapTag$2)) {
386
386
  getTag = function(value) {
387
387
  var result = baseGetTag(value),
388
388
  Ctor = result == objectTag$4 ? value.constructor : undefined,
@@ -444,13 +444,13 @@
444
444
  }
445
445
 
446
446
  /** Used for built-in method references. */
447
- var objectProto$g = Object.prototype;
447
+ var objectProto$h = Object.prototype;
448
448
 
449
449
  /** Used to check objects for own properties. */
450
- var hasOwnProperty$e = objectProto$g.hasOwnProperty;
450
+ var hasOwnProperty$f = objectProto$h.hasOwnProperty;
451
451
 
452
452
  /** Built-in value references. */
453
- var propertyIsEnumerable$1 = objectProto$g.propertyIsEnumerable;
453
+ var propertyIsEnumerable$1 = objectProto$h.propertyIsEnumerable;
454
454
 
455
455
  /**
456
456
  * Checks if `value` is likely an `arguments` object.
@@ -471,7 +471,7 @@
471
471
  * // => false
472
472
  */
473
473
  var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
474
- return isObjectLike(value) && hasOwnProperty$e.call(value, 'callee') &&
474
+ return isObjectLike(value) && hasOwnProperty$f.call(value, 'callee') &&
475
475
  !propertyIsEnumerable$1.call(value, 'callee');
476
476
  };
477
477
 
@@ -736,10 +736,10 @@
736
736
  setTag$4 = '[object Set]';
737
737
 
738
738
  /** Used for built-in method references. */
739
- var objectProto$f = Object.prototype;
739
+ var objectProto$g = Object.prototype;
740
740
 
741
741
  /** Used to check objects for own properties. */
742
- var hasOwnProperty$d = objectProto$f.hasOwnProperty;
742
+ var hasOwnProperty$e = objectProto$g.hasOwnProperty;
743
743
 
744
744
  /**
745
745
  * Checks if `value` is an empty object, collection, map, or set.
@@ -791,7 +791,7 @@
791
791
  return !baseKeys(value).length;
792
792
  }
793
793
  for (var key in value) {
794
- if (hasOwnProperty$d.call(value, key)) {
794
+ if (hasOwnProperty$e.call(value, key)) {
795
795
  return false;
796
796
  }
797
797
  }
@@ -842,10 +842,10 @@
842
842
  }
843
843
 
844
844
  /** Used for built-in method references. */
845
- var objectProto$e = Object.prototype;
845
+ var objectProto$f = Object.prototype;
846
846
 
847
847
  /** Used to check objects for own properties. */
848
- var hasOwnProperty$c = objectProto$e.hasOwnProperty;
848
+ var hasOwnProperty$d = objectProto$f.hasOwnProperty;
849
849
 
850
850
  /**
851
851
  * Creates an array of the enumerable property names of the array-like `value`.
@@ -865,7 +865,7 @@
865
865
  length = result.length;
866
866
 
867
867
  for (var key in value) {
868
- if ((inherited || hasOwnProperty$c.call(value, key)) &&
868
+ if ((inherited || hasOwnProperty$d.call(value, key)) &&
869
869
  !(skipIndexes && (
870
870
  // Safari 9 has enumerable `arguments.length` in strict mode.
871
871
  key == 'length' ||
@@ -1008,7 +1008,7 @@
1008
1008
  * _.toString([1, 2, 3]);
1009
1009
  * // => '1,2,3'
1010
1010
  */
1011
- function toString$2(value) {
1011
+ function toString$1(value) {
1012
1012
  return value == null ? '' : baseToString(value);
1013
1013
  }
1014
1014
 
@@ -1034,7 +1034,7 @@
1034
1034
  */
1035
1035
  function uniqueId(prefix) {
1036
1036
  var id = ++idCounter;
1037
- return toString$2(prefix) + id;
1037
+ return toString$1(prefix) + id;
1038
1038
  }
1039
1039
 
1040
1040
  /** Used to match a single whitespace character. */
@@ -1630,6 +1630,14 @@
1630
1630
  eventsApi(triggerApi, this._events, name, undefined, args);
1631
1631
  return this;
1632
1632
  }
1633
+ /**
1634
+ * Subscribe to an event. Returns an unsubscribe function.
1635
+ * Compatible with `useSyncExternalStore` and other store-style APIs.
1636
+ */
1637
+ subscribe(event, callback, context) {
1638
+ this.on(event, callback, context);
1639
+ return () => this.off(event, callback, context);
1640
+ }
1633
1641
  };
1634
1642
  }
1635
1643
  /**
@@ -1637,7 +1645,7 @@
1637
1645
  */
1638
1646
  const EventEmitterObject = EventEmitter(Object);
1639
1647
 
1640
- /*! *****************************************************************************
1648
+ /******************************************************************************
1641
1649
  Copyright (c) Microsoft Corporation.
1642
1650
 
1643
1651
  Permission to use, copy, modify, and/or distribute this software for any
@@ -1651,7 +1659,7 @@
1651
1659
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1652
1660
  PERFORMANCE OF THIS SOFTWARE.
1653
1661
  ***************************************************************************** */
1654
- /* global Reflect, Promise */
1662
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
1655
1663
 
1656
1664
 
1657
1665
  function __values(o) {
@@ -1664,7 +1672,25 @@
1664
1672
  }
1665
1673
  };
1666
1674
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
1667
- }
1675
+ }
1676
+
1677
+ function __classPrivateFieldGet(receiver, state, kind, f) {
1678
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
1679
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
1680
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
1681
+ }
1682
+
1683
+ function __classPrivateFieldSet(receiver, state, value, kind, f) {
1684
+ if (kind === "m") throw new TypeError("Private method is not writable");
1685
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
1686
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
1687
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
1688
+ }
1689
+
1690
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1691
+ var e = new Error(message);
1692
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1693
+ };
1668
1694
 
1669
1695
  /*!
1670
1696
  MIT License
@@ -1703,7 +1729,7 @@
1703
1729
  * @param parts
1704
1730
  * @param properties
1705
1731
  */
1706
- function createBlob$1(parts, properties) {
1732
+ function createBlob(parts, properties) {
1707
1733
  /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */
1708
1734
  parts = parts || [];
1709
1735
  properties = properties || {};
@@ -1727,12 +1753,12 @@
1727
1753
  }
1728
1754
  }
1729
1755
 
1730
- var BLOB_TYPE_PREFIX_REGEX$1 = /^~~local_forage_type~([^~]+)~/;
1731
- var SERIALIZED_MARKER_LENGTH$1 = "__lfsc__:" /* SERIALIZED_MARKER */.length;
1732
- var TYPE_SERIALIZED_MARKER_LENGTH$1 = SERIALIZED_MARKER_LENGTH$1 + "arbf" /* TYPE_ARRAYBUFFER */.length;
1756
+ var BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;
1757
+ var SERIALIZED_MARKER_LENGTH = "__lfsc__:" /* SERIALIZED_MARKER */.length;
1758
+ var TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH + "arbf" /* TYPE_ARRAYBUFFER */.length;
1733
1759
  //tslint:disable:no-magic-numbers no-bitwise prefer-switch no-unbound-method
1734
- var toString$1 = Object.prototype.toString;
1735
- function stringToBuffer$1(serializedString) {
1760
+ var toString = Object.prototype.toString;
1761
+ function stringToBuffer(serializedString) {
1736
1762
  // Fill the string into a ArrayBuffer.
1737
1763
  var bufferLength = serializedString.length * 0.75;
1738
1764
  var len = serializedString.length;
@@ -1759,7 +1785,7 @@
1759
1785
  * Converts a buffer to a string to store, serialized, in the backend
1760
1786
  * storage library.
1761
1787
  */
1762
- function bufferToString$1(buffer) {
1788
+ function bufferToString(buffer) {
1763
1789
  // base64-arraybuffer
1764
1790
  var bytes = new Uint8Array(buffer);
1765
1791
  var base64String = '';
@@ -1786,15 +1812,15 @@
1786
1812
  * @param value
1787
1813
  * @param callback
1788
1814
  */
1789
- function serialize$2(value, callback) {
1815
+ function serialize$1(value, callback) {
1790
1816
  var valueType = '';
1791
1817
  if (value) {
1792
- valueType = toString$1.call(value);
1818
+ valueType = toString.call(value);
1793
1819
  }
1794
1820
  // Cannot use `value instanceof ArrayBuffer` or such here, as these
1795
1821
  // checks fail when running the tests using casper.js...
1796
1822
  if (value && (valueType === '[object ArrayBuffer]' ||
1797
- (value.buffer && toString$1.call(value.buffer) === '[object ArrayBuffer]'))) {
1823
+ (value.buffer && toString.call(value.buffer) === '[object ArrayBuffer]'))) {
1798
1824
  // Convert binary arrays to a string and prefix the string with
1799
1825
  // a special marker.
1800
1826
  var buffer = void 0;
@@ -1836,7 +1862,7 @@
1836
1862
  callback(new Error('Failed to get type for BinaryArray'));
1837
1863
  }
1838
1864
  }
1839
- callback(marker + bufferToString$1(buffer));
1865
+ callback(marker + bufferToString(buffer));
1840
1866
  }
1841
1867
  else if (valueType === '[object Blob]') {
1842
1868
  // Convert the blob to a binaryArray and then to a string.
@@ -1844,7 +1870,7 @@
1844
1870
  fileReader.onload = function () {
1845
1871
  // Backwards-compatible prefix for the blob type.
1846
1872
  //tslint:disable-next-line:restrict-plus-operands
1847
- var str = "~~local_forage_type~" /* BLOB_TYPE_PREFIX */ + value.type + "~" + bufferToString$1(this.result);
1873
+ var str = "~~local_forage_type~" /* BLOB_TYPE_PREFIX */ + value.type + "~" + bufferToString(this.result);
1848
1874
  callback("__lfsc__:" /* SERIALIZED_MARKER */ + "blob" /* TYPE_BLOB */ + str);
1849
1875
  };
1850
1876
  fileReader.readAsArrayBuffer(value);
@@ -1870,34 +1896,34 @@
1870
1896
  * some kind of arraybuffer/binary data/typed array out of the string.
1871
1897
  * @param value
1872
1898
  */
1873
- function deserialize$2(value) {
1899
+ function deserialize$1(value) {
1874
1900
  // If we haven't marked this string as being specially serialized (i.e.
1875
1901
  // something other than serialized JSON), we can just return it and be
1876
1902
  // done with it.
1877
- if (value.substring(0, SERIALIZED_MARKER_LENGTH$1) !== "__lfsc__:" /* SERIALIZED_MARKER */) {
1903
+ if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== "__lfsc__:" /* SERIALIZED_MARKER */) {
1878
1904
  return JSON.parse(value);
1879
1905
  }
1880
1906
  // The following code deals with deserializing some kind of Blob or
1881
1907
  // TypedArray. First we separate out the type of data we're dealing
1882
1908
  // with from the data itself.
1883
- var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH$1);
1884
- var type = value.substring(SERIALIZED_MARKER_LENGTH$1, TYPE_SERIALIZED_MARKER_LENGTH$1);
1909
+ var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
1910
+ var type = value.substring(SERIALIZED_MARKER_LENGTH, TYPE_SERIALIZED_MARKER_LENGTH);
1885
1911
  var blobType;
1886
1912
  // Backwards-compatible blob type serialization strategy.
1887
1913
  // DBs created with older versions of localForage will simply not have the blob type.
1888
- if (type === "blob" /* TYPE_BLOB */ && BLOB_TYPE_PREFIX_REGEX$1.test(serializedString)) {
1889
- var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX$1);
1914
+ if (type === "blob" /* TYPE_BLOB */ && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {
1915
+ var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);
1890
1916
  blobType = matcher[1];
1891
1917
  serializedString = serializedString.substring(matcher[0].length);
1892
1918
  }
1893
- var buffer = stringToBuffer$1(serializedString);
1919
+ var buffer = stringToBuffer(serializedString);
1894
1920
  // Return the right type based on the code/type set during
1895
1921
  // serialization.
1896
1922
  switch (type) {
1897
1923
  case "arbf" /* TYPE_ARRAYBUFFER */:
1898
1924
  return buffer;
1899
1925
  case "blob" /* TYPE_BLOB */:
1900
- return createBlob$1([buffer], { type: blobType });
1926
+ return createBlob([buffer], { type: blobType });
1901
1927
  case "si08" /* TYPE_INT8ARRAY */:
1902
1928
  return new Int8Array(buffer);
1903
1929
  case "ui08" /* TYPE_UINT8ARRAY */:
@@ -1951,7 +1977,7 @@
1951
1977
  return (options.name || defaultConfig.name) + "/" + (options.storeName || defaultConfig.storeName) + "/";
1952
1978
  }
1953
1979
 
1954
- function executeCallback$2(promise, callback) {
1980
+ function executeCallback$1(promise, callback) {
1955
1981
  if (callback) {
1956
1982
  promise.then(function (result) {
1957
1983
  callback(null, result);
@@ -2004,10 +2030,10 @@
2004
2030
  }
2005
2031
 
2006
2032
  var serialiser = {
2007
- bufferToString: bufferToString$1,
2008
- deserialize: deserialize$2,
2009
- serialize: serialize$2,
2010
- stringToBuffer: stringToBuffer$1
2033
+ bufferToString: bufferToString,
2034
+ deserialize: deserialize$1,
2035
+ serialize: serialize$1,
2036
+ stringToBuffer: stringToBuffer
2011
2037
  };
2012
2038
 
2013
2039
  /*!
@@ -2092,7 +2118,7 @@
2092
2118
  var promise = this.ready().then(function () {
2093
2119
  _this._dbInfo.mStore.clear();
2094
2120
  });
2095
- executeCallback$2(promise, callback);
2121
+ executeCallback$1(promise, callback);
2096
2122
  return promise;
2097
2123
  }
2098
2124
 
@@ -2101,7 +2127,7 @@
2101
2127
  var outPromise = promise.then(function (keyPrefix) {
2102
2128
  Store.resolve(keyPrefix).drop();
2103
2129
  });
2104
- executeCallback$2(outPromise, callback);
2130
+ executeCallback$1(outPromise, callback);
2105
2131
  return promise;
2106
2132
  }
2107
2133
 
@@ -2113,7 +2139,7 @@
2113
2139
  // Deserialise if the result is not null or undefined
2114
2140
  return result == null ? null : _this._dbInfo.serializer.deserialize(result); //tslint:disable-line:triple-equals
2115
2141
  });
2116
- executeCallback$2(promise, callback);
2142
+ executeCallback$1(promise, callback);
2117
2143
  return promise;
2118
2144
  }
2119
2145
 
@@ -2137,7 +2163,7 @@
2137
2163
  }
2138
2164
  }
2139
2165
  });
2140
- executeCallback$2(promise, callback);
2166
+ executeCallback$1(promise, callback);
2141
2167
  return promise;
2142
2168
  }
2143
2169
 
@@ -2156,7 +2182,7 @@
2156
2182
  }
2157
2183
  return result;
2158
2184
  });
2159
- executeCallback$2(promise, callback);
2185
+ executeCallback$1(promise, callback);
2160
2186
  return promise;
2161
2187
  }
2162
2188
 
@@ -2165,13 +2191,13 @@
2165
2191
  var promise = this.ready().then(function () {
2166
2192
  return _this._dbInfo.mStore.keys();
2167
2193
  });
2168
- executeCallback$2(promise, callback);
2194
+ executeCallback$1(promise, callback);
2169
2195
  return promise;
2170
2196
  }
2171
2197
 
2172
2198
  function length$1(callback) {
2173
2199
  var promise = this.keys().then(function (keys$) { return keys$.length; });
2174
- executeCallback$2(promise, callback);
2200
+ executeCallback$1(promise, callback);
2175
2201
  return promise;
2176
2202
  }
2177
2203
 
@@ -2181,7 +2207,7 @@
2181
2207
  var promise = this.ready().then(function () {
2182
2208
  _this._dbInfo.mStore.rm(key$);
2183
2209
  });
2184
- executeCallback$2(promise, callback);
2210
+ executeCallback$1(promise, callback);
2185
2211
  return promise;
2186
2212
  }
2187
2213
 
@@ -2211,7 +2237,7 @@
2211
2237
  });
2212
2238
  });
2213
2239
  });
2214
- executeCallback$2(promise, callback);
2240
+ executeCallback$1(promise, callback);
2215
2241
  return promise;
2216
2242
  }
2217
2243
 
@@ -2498,10 +2524,10 @@
2498
2524
  var HASH_UNDEFINED$2 = '__lodash_hash_undefined__';
2499
2525
 
2500
2526
  /** Used for built-in method references. */
2501
- var objectProto$d = Object.prototype;
2527
+ var objectProto$e = Object.prototype;
2502
2528
 
2503
2529
  /** Used to check objects for own properties. */
2504
- var hasOwnProperty$b = objectProto$d.hasOwnProperty;
2530
+ var hasOwnProperty$c = objectProto$e.hasOwnProperty;
2505
2531
 
2506
2532
  /**
2507
2533
  * Gets the hash value for `key`.
@@ -2518,14 +2544,14 @@
2518
2544
  var result = data[key];
2519
2545
  return result === HASH_UNDEFINED$2 ? undefined : result;
2520
2546
  }
2521
- return hasOwnProperty$b.call(data, key) ? data[key] : undefined;
2547
+ return hasOwnProperty$c.call(data, key) ? data[key] : undefined;
2522
2548
  }
2523
2549
 
2524
2550
  /** Used for built-in method references. */
2525
- var objectProto$c = Object.prototype;
2551
+ var objectProto$d = Object.prototype;
2526
2552
 
2527
2553
  /** Used to check objects for own properties. */
2528
- var hasOwnProperty$a = objectProto$c.hasOwnProperty;
2554
+ var hasOwnProperty$b = objectProto$d.hasOwnProperty;
2529
2555
 
2530
2556
  /**
2531
2557
  * Checks if a hash value for `key` exists.
@@ -2538,7 +2564,7 @@
2538
2564
  */
2539
2565
  function hashHas(key) {
2540
2566
  var data = this.__data__;
2541
- return nativeCreate ? (data[key] !== undefined) : hasOwnProperty$a.call(data, key);
2567
+ return nativeCreate ? (data[key] !== undefined) : hasOwnProperty$b.call(data, key);
2542
2568
  }
2543
2569
 
2544
2570
  /** Used to stand-in for `undefined` hash values. */
@@ -2597,7 +2623,7 @@
2597
2623
  this.size = 0;
2598
2624
  this.__data__ = {
2599
2625
  'hash': new Hash,
2600
- 'map': new (Map || ListCache),
2626
+ 'map': new (Map$1 || ListCache),
2601
2627
  'string': new Hash
2602
2628
  };
2603
2629
  }
@@ -2733,7 +2759,7 @@
2733
2759
  var data = this.__data__;
2734
2760
  if (data instanceof ListCache) {
2735
2761
  var pairs = data.__data__;
2736
- if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
2762
+ if (!Map$1 || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
2737
2763
  pairs.push([key, value]);
2738
2764
  this.size = ++data.size;
2739
2765
  return this;
@@ -2816,10 +2842,10 @@
2816
2842
  }
2817
2843
 
2818
2844
  /** Used for built-in method references. */
2819
- var objectProto$b = Object.prototype;
2845
+ var objectProto$c = Object.prototype;
2820
2846
 
2821
2847
  /** Used to check objects for own properties. */
2822
- var hasOwnProperty$9 = objectProto$b.hasOwnProperty;
2848
+ var hasOwnProperty$a = objectProto$c.hasOwnProperty;
2823
2849
 
2824
2850
  /**
2825
2851
  * Assigns `value` to `key` of `object` if the existing value is not equivalent
@@ -2833,7 +2859,7 @@
2833
2859
  */
2834
2860
  function assignValue(object, key, value) {
2835
2861
  var objValue = object[key];
2836
- if (!(hasOwnProperty$9.call(object, key) && eq(objValue, value)) ||
2862
+ if (!(hasOwnProperty$a.call(object, key) && eq(objValue, value)) ||
2837
2863
  (value === undefined && !(key in object))) {
2838
2864
  baseAssignValue(object, key, value);
2839
2865
  }
@@ -2906,10 +2932,10 @@
2906
2932
  }
2907
2933
 
2908
2934
  /** Used for built-in method references. */
2909
- var objectProto$a = Object.prototype;
2935
+ var objectProto$b = Object.prototype;
2910
2936
 
2911
2937
  /** Used to check objects for own properties. */
2912
- var hasOwnProperty$8 = objectProto$a.hasOwnProperty;
2938
+ var hasOwnProperty$9 = objectProto$b.hasOwnProperty;
2913
2939
 
2914
2940
  /**
2915
2941
  * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
@@ -2926,7 +2952,7 @@
2926
2952
  result = [];
2927
2953
 
2928
2954
  for (var key in object) {
2929
- if (!(key == 'constructor' && (isProto || !hasOwnProperty$8.call(object, key)))) {
2955
+ if (!(key == 'constructor' && (isProto || !hasOwnProperty$9.call(object, key)))) {
2930
2956
  result.push(key);
2931
2957
  }
2932
2958
  }
@@ -3071,10 +3097,10 @@
3071
3097
  }
3072
3098
 
3073
3099
  /** Used for built-in method references. */
3074
- var objectProto$9 = Object.prototype;
3100
+ var objectProto$a = Object.prototype;
3075
3101
 
3076
3102
  /** Built-in value references. */
3077
- var propertyIsEnumerable = objectProto$9.propertyIsEnumerable;
3103
+ var propertyIsEnumerable = objectProto$a.propertyIsEnumerable;
3078
3104
 
3079
3105
  /* Built-in method references for those with the same name as other `lodash` methods. */
3080
3106
  var nativeGetSymbols$1 = Object.getOwnPropertySymbols;
@@ -3201,10 +3227,10 @@
3201
3227
  }
3202
3228
 
3203
3229
  /** Used for built-in method references. */
3204
- var objectProto$8 = Object.prototype;
3230
+ var objectProto$9 = Object.prototype;
3205
3231
 
3206
3232
  /** Used to check objects for own properties. */
3207
- var hasOwnProperty$7 = objectProto$8.hasOwnProperty;
3233
+ var hasOwnProperty$8 = objectProto$9.hasOwnProperty;
3208
3234
 
3209
3235
  /**
3210
3236
  * Initializes an array clone.
@@ -3218,7 +3244,7 @@
3218
3244
  result = new array.constructor(length);
3219
3245
 
3220
3246
  // Add properties assigned by `RegExp#exec`.
3221
- if (length && typeof array[0] == 'string' && hasOwnProperty$7.call(array, 'index')) {
3247
+ if (length && typeof array[0] == 'string' && hasOwnProperty$8.call(array, 'index')) {
3222
3248
  result.index = array.index;
3223
3249
  result.input = array.input;
3224
3250
  }
@@ -6598,13 +6624,13 @@
6598
6624
 
6599
6625
  /** Used for built-in method references. */
6600
6626
  var funcProto = Function.prototype,
6601
- objectProto$7 = Object.prototype;
6627
+ objectProto$8 = Object.prototype;
6602
6628
 
6603
6629
  /** Used to resolve the decompiled source of functions. */
6604
6630
  var funcToString = funcProto.toString;
6605
6631
 
6606
6632
  /** Used to check objects for own properties. */
6607
- var hasOwnProperty$6 = objectProto$7.hasOwnProperty;
6633
+ var hasOwnProperty$7 = objectProto$8.hasOwnProperty;
6608
6634
 
6609
6635
  /** Used to infer the `Object` constructor. */
6610
6636
  var objectCtorString = funcToString.call(Object);
@@ -6645,7 +6671,7 @@
6645
6671
  if (proto === null) {
6646
6672
  return true;
6647
6673
  }
6648
- var Ctor = hasOwnProperty$6.call(proto, 'constructor') && proto.constructor;
6674
+ var Ctor = hasOwnProperty$7.call(proto, 'constructor') && proto.constructor;
6649
6675
  return typeof Ctor == 'function' && Ctor instanceof Ctor &&
6650
6676
  funcToString.call(Ctor) == objectCtorString;
6651
6677
  }
@@ -7377,310 +7403,43 @@
7377
7403
  return debounced;
7378
7404
  }
7379
7405
 
7380
- function executeCallback$1(promise, callback) {
7406
+ function chainCallback(promise, callback) {
7381
7407
  if (callback) {
7382
- promise.then(
7383
- function(result) {
7384
- callback(null, result);
7385
- },
7386
- function(error) {
7387
- callback(error);
7388
- }
7389
- );
7408
+ promise.then((result) => callback(null, result), (err) => callback(err));
7390
7409
  }
7391
7410
  }
7392
-
7393
- function getCallback() {
7394
- if (
7395
- arguments.length &&
7396
- typeof arguments[arguments.length - 1] === 'function'
7397
- ) {
7398
- return arguments[arguments.length - 1];
7411
+ function getCallback(...args) {
7412
+ if (args.length && typeof args[args.length - 1] === 'function') {
7413
+ return args[args.length - 1];
7399
7414
  }
7400
7415
  }
7401
-
7402
7416
  function normalizeKey(key) {
7403
- // Cast the key to a string, as that's all we can set as a key.
7404
7417
  if (typeof key !== 'string') {
7405
7418
  console.warn(`${key} used as a key, but it is not a string.`);
7406
7419
  key = String(key);
7407
7420
  }
7408
-
7409
7421
  return key;
7410
7422
  }
7411
-
7412
- // Abstracts constructing a Blob object, so it also works in older
7413
- // browsers that don't support the native Blob constructor. (i.e.
7414
- // old QtWebKit versions, at least).
7415
- // Abstracts constructing a Blob object, so it also works in older
7416
- // browsers that don't support the native Blob constructor. (i.e.
7417
- // old QtWebKit versions, at least).
7418
- function createBlob(parts, properties) {
7419
- /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */
7420
- parts = parts || [];
7421
- properties = properties || {};
7422
- try {
7423
- return new Blob(parts, properties);
7424
- } catch (e) {
7425
- if (e.name !== 'TypeError') {
7426
- throw e;
7427
- }
7428
- var Builder =
7429
- typeof BlobBuilder !== 'undefined'
7430
- ? BlobBuilder
7431
- : typeof MSBlobBuilder !== 'undefined'
7432
- ? MSBlobBuilder
7433
- : typeof MozBlobBuilder !== 'undefined'
7434
- ? MozBlobBuilder
7435
- : WebKitBlobBuilder;
7436
- var builder = new Builder();
7437
- for (var i = 0; i < parts.length; i += 1) {
7438
- builder.append(parts[i]);
7423
+ function serializeSync(value) {
7424
+ return JSON.stringify(value, (_key, val) => {
7425
+ if (val instanceof Date) {
7426
+ return val.toISOString();
7439
7427
  }
7440
- return builder.getBlob(properties.type);
7441
- }
7442
- }
7443
-
7444
- /* eslint-disable no-bitwise */
7445
-
7446
- // Sadly, the best way to save binary data in WebSQL/localStorage is serializing
7447
- // it to Base64, so this is how we store it to prevent very strange errors with less
7448
- // verbose ways of binary <-> string data storage.
7449
- var BASE_CHARS =
7450
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
7451
-
7452
- var BLOB_TYPE_PREFIX = '~~local_forage_type~';
7453
- var BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;
7454
-
7455
- var SERIALIZED_MARKER = '__lfsc__:';
7456
- var SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length;
7457
-
7458
- // OMG the serializations!
7459
- var TYPE_ARRAYBUFFER = 'arbf';
7460
- var TYPE_BLOB = 'blob';
7461
- var TYPE_INT8ARRAY = 'si08';
7462
- var TYPE_UINT8ARRAY = 'ui08';
7463
- var TYPE_UINT8CLAMPEDARRAY = 'uic8';
7464
- var TYPE_INT16ARRAY = 'si16';
7465
- var TYPE_INT32ARRAY = 'si32';
7466
- var TYPE_UINT16ARRAY = 'ur16';
7467
- var TYPE_UINT32ARRAY = 'ui32';
7468
- var TYPE_FLOAT32ARRAY = 'fl32';
7469
- var TYPE_FLOAT64ARRAY = 'fl64';
7470
- var TYPE_SERIALIZED_MARKER_LENGTH =
7471
- SERIALIZED_MARKER_LENGTH + TYPE_ARRAYBUFFER.length;
7472
-
7473
- var toString = Object.prototype.toString;
7474
-
7475
- function stringToBuffer(serializedString) {
7476
- // Fill the string into a ArrayBuffer.
7477
- var bufferLength = serializedString.length * 0.75;
7478
- var len = serializedString.length;
7479
- var i;
7480
- var p = 0;
7481
- var encoded1, encoded2, encoded3, encoded4;
7482
-
7483
- if (serializedString[serializedString.length - 1] === '=') {
7484
- bufferLength--;
7485
- if (serializedString[serializedString.length - 2] === '=') {
7486
- bufferLength--;
7487
- }
7488
- }
7489
-
7490
- var buffer = new ArrayBuffer(bufferLength);
7491
- var bytes = new Uint8Array(buffer);
7492
-
7493
- for (i = 0; i < len; i += 4) {
7494
- encoded1 = BASE_CHARS.indexOf(serializedString[i]);
7495
- encoded2 = BASE_CHARS.indexOf(serializedString[i + 1]);
7496
- encoded3 = BASE_CHARS.indexOf(serializedString[i + 2]);
7497
- encoded4 = BASE_CHARS.indexOf(serializedString[i + 3]);
7498
-
7499
- /*jslint bitwise: true */
7500
- bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
7501
- bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
7502
- bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
7503
- }
7504
- return buffer;
7428
+ return val;
7429
+ });
7505
7430
  }
7506
-
7507
- // Converts a buffer to a string to store, serialized, in the backend
7508
- // storage library.
7509
- function bufferToString(buffer) {
7510
- // base64-arraybuffer
7511
- var bytes = new Uint8Array(buffer);
7512
- var base64String = '';
7513
- var i;
7514
-
7515
- for (i = 0; i < bytes.length; i += 3) {
7516
- /*jslint bitwise: true */
7517
- base64String += BASE_CHARS[bytes[i] >> 2];
7518
- base64String += BASE_CHARS[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
7519
- base64String +=
7520
- BASE_CHARS[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
7521
- base64String += BASE_CHARS[bytes[i + 2] & 63];
7431
+ function serialize(value, callback) {
7432
+ try {
7433
+ callback(serializeSync(value), null);
7522
7434
  }
7523
-
7524
- if (bytes.length % 3 === 2) {
7525
- base64String = base64String.substring(0, base64String.length - 1) + '=';
7526
- } else if (bytes.length % 3 === 1) {
7527
- base64String =
7528
- base64String.substring(0, base64String.length - 2) + '==';
7435
+ catch (e) {
7436
+ callback('', e);
7529
7437
  }
7530
-
7531
- return base64String;
7532
7438
  }
7533
-
7534
- // Serialize a value, afterwards executing a callback (which usually
7535
- // instructs the `setItem()` callback/promise to be executed). This is how
7536
- // we store binary data with localStorage.
7537
- function serialize$1(value, callback) {
7538
- var valueType = '';
7539
- if (value) {
7540
- valueType = toString.call(value);
7541
- }
7542
-
7543
- // Cannot use `value instanceof ArrayBuffer` or such here, as these
7544
- // checks fail when running the tests using casper.js...
7545
- //
7546
- // TODO: See why those tests fail and use a better solution.
7547
- if (
7548
- value &&
7549
- (valueType === '[object ArrayBuffer]' ||
7550
- (value.buffer &&
7551
- toString.call(value.buffer) === '[object ArrayBuffer]'))
7552
- ) {
7553
- // Convert binary arrays to a string and prefix the string with
7554
- // a special marker.
7555
- var buffer;
7556
- var marker = SERIALIZED_MARKER;
7557
-
7558
- if (value instanceof ArrayBuffer) {
7559
- buffer = value;
7560
- marker += TYPE_ARRAYBUFFER;
7561
- } else {
7562
- buffer = value.buffer;
7563
-
7564
- if (valueType === '[object Int8Array]') {
7565
- marker += TYPE_INT8ARRAY;
7566
- } else if (valueType === '[object Uint8Array]') {
7567
- marker += TYPE_UINT8ARRAY;
7568
- } else if (valueType === '[object Uint8ClampedArray]') {
7569
- marker += TYPE_UINT8CLAMPEDARRAY;
7570
- } else if (valueType === '[object Int16Array]') {
7571
- marker += TYPE_INT16ARRAY;
7572
- } else if (valueType === '[object Uint16Array]') {
7573
- marker += TYPE_UINT16ARRAY;
7574
- } else if (valueType === '[object Int32Array]') {
7575
- marker += TYPE_INT32ARRAY;
7576
- } else if (valueType === '[object Uint32Array]') {
7577
- marker += TYPE_UINT32ARRAY;
7578
- } else if (valueType === '[object Float32Array]') {
7579
- marker += TYPE_FLOAT32ARRAY;
7580
- } else if (valueType === '[object Float64Array]') {
7581
- marker += TYPE_FLOAT64ARRAY;
7582
- } else {
7583
- callback(new Error('Failed to get type for BinaryArray'));
7584
- }
7585
- }
7586
-
7587
- callback(marker + bufferToString(buffer));
7588
- } else if (valueType === '[object Blob]') {
7589
- // Conver the blob to a binaryArray and then to a string.
7590
- var fileReader = new FileReader();
7591
-
7592
- fileReader.onload = function() {
7593
- // Backwards-compatible prefix for the blob type.
7594
- var str =
7595
- BLOB_TYPE_PREFIX +
7596
- value.type +
7597
- '~' +
7598
- bufferToString(this.result);
7599
-
7600
- callback(SERIALIZED_MARKER + TYPE_BLOB + str);
7601
- };
7602
-
7603
- fileReader.readAsArrayBuffer(value);
7604
- } else {
7605
- try {
7606
- callback(JSON.stringify(value));
7607
- } catch (e) {
7608
- console.error("Couldn't convert value into a JSON string: ", value);
7609
-
7610
- callback(null, e);
7611
- }
7612
- }
7439
+ function deserialize(value) {
7440
+ return JSON.parse(value);
7613
7441
  }
7614
7442
 
7615
- // Deserialize data we've inserted into a value column/field. We place
7616
- // special markers into our strings to mark them as encoded; this isn't
7617
- // as nice as a meta field, but it's the only sane thing we can do whilst
7618
- // keeping localStorage support intact.
7619
- //
7620
- // Oftentimes this will just deserialize JSON content, but if we have a
7621
- // special marker (SERIALIZED_MARKER, defined above), we will extract
7622
- // some kind of arraybuffer/binary data/typed array out of the string.
7623
- function deserialize$1(value) {
7624
- // If we haven't marked this string as being specially serialized (i.e.
7625
- // something other than serialized JSON), we can just return it and be
7626
- // done with it.
7627
- if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {
7628
- return JSON.parse(value);
7629
- }
7630
-
7631
- // The following code deals with deserializing some kind of Blob or
7632
- // TypedArray. First we separate out the type of data we're dealing
7633
- // with from the data itself.
7634
- var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
7635
- var type = value.substring(
7636
- SERIALIZED_MARKER_LENGTH,
7637
- TYPE_SERIALIZED_MARKER_LENGTH
7638
- );
7639
-
7640
- var blobType;
7641
- // Backwards-compatible blob type serialization strategy.
7642
- // DBs created with older versions of localForage will simply not have the blob type.
7643
- if (type === TYPE_BLOB && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {
7644
- var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);
7645
- blobType = matcher[1];
7646
- serializedString = serializedString.substring(matcher[0].length);
7647
- }
7648
- var buffer = stringToBuffer(serializedString);
7649
-
7650
- // Return the right type based on the code/type set during
7651
- // serialization.
7652
- switch (type) {
7653
- case TYPE_ARRAYBUFFER:
7654
- return buffer;
7655
- case TYPE_BLOB:
7656
- return createBlob([buffer], { type: blobType });
7657
- case TYPE_INT8ARRAY:
7658
- return new Int8Array(buffer);
7659
- case TYPE_UINT8ARRAY:
7660
- return new Uint8Array(buffer);
7661
- case TYPE_UINT8CLAMPEDARRAY:
7662
- return new Uint8ClampedArray(buffer);
7663
- case TYPE_INT16ARRAY:
7664
- return new Int16Array(buffer);
7665
- case TYPE_UINT16ARRAY:
7666
- return new Uint16Array(buffer);
7667
- case TYPE_INT32ARRAY:
7668
- return new Int32Array(buffer);
7669
- case TYPE_UINT32ARRAY:
7670
- return new Uint32Array(buffer);
7671
- case TYPE_FLOAT32ARRAY:
7672
- return new Float32Array(buffer);
7673
- case TYPE_FLOAT64ARRAY:
7674
- return new Float64Array(buffer);
7675
- default:
7676
- throw new Error('Unkown type: ' + type);
7677
- }
7678
- }
7679
-
7680
- var localforageSerializer = {
7681
- serialize: serialize$1,
7682
- deserialize: deserialize$1};
7683
-
7684
7443
  // Copyright 2014 Mozilla
7685
7444
  // Copyright 2015 Thodoris Greasidis
7686
7445
  // Copyright 2018-2025 JC Brand
@@ -7696,8 +7455,6 @@
7696
7455
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7697
7456
  // See the License for the specific language governing permissions and
7698
7457
  // limitations under the License.
7699
- const serialize = localforageSerializer['serialize'];
7700
- const deserialize = localforageSerializer['deserialize'];
7701
7458
  function isSessionStorageValid() {
7702
7459
  try {
7703
7460
  if (sessionStorage && 'setItem' in sessionStorage) {
@@ -7743,7 +7500,7 @@
7743
7500
  }
7744
7501
  }
7745
7502
  });
7746
- executeCallback$1(promise, callback);
7503
+ chainCallback(promise, callback);
7747
7504
  return promise;
7748
7505
  }
7749
7506
  function getItem(key, callback) {
@@ -7759,7 +7516,7 @@
7759
7516
  }
7760
7517
  return null;
7761
7518
  });
7762
- executeCallback$1(promise, callback);
7519
+ chainCallback(promise, callback);
7763
7520
  return promise;
7764
7521
  }
7765
7522
  function iterate(iterator, callback) {
@@ -7787,7 +7544,7 @@
7787
7544
  }
7788
7545
  return;
7789
7546
  });
7790
- executeCallback$1(promise, callback);
7547
+ chainCallback(promise, callback);
7791
7548
  return promise;
7792
7549
  }
7793
7550
  // Same as sessionStorage's key() method, except takes a callback.
@@ -7807,7 +7564,7 @@
7807
7564
  }
7808
7565
  return result;
7809
7566
  });
7810
- executeCallback$1(promise, callback);
7567
+ chainCallback(promise, callback);
7811
7568
  return promise;
7812
7569
  }
7813
7570
  function keys(callback) {
@@ -7823,7 +7580,7 @@
7823
7580
  }
7824
7581
  return keys;
7825
7582
  });
7826
- executeCallback$1(promise, callback);
7583
+ chainCallback(promise, callback);
7827
7584
  return promise;
7828
7585
  }
7829
7586
  // Supply the number of keys in the datastore to the callback function.
@@ -7832,7 +7589,7 @@
7832
7589
  const promise = self.keys().then(function (keys) {
7833
7590
  return keys.length;
7834
7591
  });
7835
- executeCallback$1(promise, callback);
7592
+ chainCallback(promise, callback);
7836
7593
  return promise;
7837
7594
  }
7838
7595
  function removeItem(key, callback) {
@@ -7840,7 +7597,7 @@
7840
7597
  const promise = this.ready().then(function () {
7841
7598
  sessionStorage.removeItem(dbInfo.keyPrefix + key);
7842
7599
  });
7843
- executeCallback$1(promise, callback);
7600
+ chainCallback(promise, callback);
7844
7601
  return promise;
7845
7602
  }
7846
7603
  async function setItem(key, value, callback) {
@@ -7852,27 +7609,27 @@
7852
7609
  dbInfo.serializer.serialize(value, (serializedValue, error) => {
7853
7610
  if (error) {
7854
7611
  reject(error);
7855
- executeCallback$1(Promise.reject(error), callback);
7612
+ chainCallback(Promise.reject(error), callback);
7856
7613
  return;
7857
7614
  }
7858
7615
  try {
7859
7616
  sessionStorage.setItem(dbInfo.keyPrefix + key, serializedValue);
7860
7617
  resolve(originalValue);
7861
- executeCallback$1(Promise.resolve(originalValue), callback);
7618
+ chainCallback(Promise.resolve(originalValue), callback);
7862
7619
  }
7863
7620
  catch (e) {
7864
7621
  if (e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
7865
7622
  console.error('Your sessionStorage capacity is used up.');
7866
7623
  }
7867
7624
  reject(e);
7868
- executeCallback$1(Promise.reject(e), callback);
7625
+ chainCallback(Promise.reject(e), callback);
7869
7626
  }
7870
7627
  });
7871
7628
  });
7872
7629
  }
7873
- function dropInstance(options, callback) {
7874
- callback = getCallback.apply(this, arguments);
7875
- options = (typeof options !== 'function' && options) || {};
7630
+ function dropInstance(...args) {
7631
+ const callback = getCallback(...args);
7632
+ let options = (typeof args[0] !== 'function' && args[0]) || {};
7876
7633
  if (!options.name) {
7877
7634
  const currentConfig = this.config();
7878
7635
  options.name = options.name || currentConfig.name;
@@ -7900,7 +7657,7 @@
7900
7657
  }
7901
7658
  });
7902
7659
  }
7903
- executeCallback$1(promise, callback);
7660
+ chainCallback(promise, callback);
7904
7661
  return promise;
7905
7662
  }
7906
7663
  const sessionStorageWrapper = {
@@ -8379,10 +8136,10 @@
8379
8136
  extendPrototype(localForage);
8380
8137
 
8381
8138
  /** Used for built-in method references. */
8382
- var objectProto$6 = Object.prototype;
8139
+ var objectProto$7 = Object.prototype;
8383
8140
 
8384
8141
  /** Used to check objects for own properties. */
8385
- var hasOwnProperty$5 = objectProto$6.hasOwnProperty;
8142
+ var hasOwnProperty$6 = objectProto$7.hasOwnProperty;
8386
8143
 
8387
8144
  /**
8388
8145
  * The base implementation of `_.has` without support for deep paths.
@@ -8393,7 +8150,7 @@
8393
8150
  * @returns {boolean} Returns `true` if `key` exists, else `false`.
8394
8151
  */
8395
8152
  function baseHas(object, key) {
8396
- return object != null && hasOwnProperty$5.call(object, key);
8153
+ return object != null && hasOwnProperty$6.call(object, key);
8397
8154
  }
8398
8155
 
8399
8156
  /** Used to match property names within property paths. */
@@ -8550,7 +8307,7 @@
8550
8307
  if (isArray(value)) {
8551
8308
  return value;
8552
8309
  }
8553
- return isKey(value, object) ? [value] : stringToPath(toString$2(value));
8310
+ return isKey(value, object) ? [value] : stringToPath(toString$1(value));
8554
8311
  }
8555
8312
 
8556
8313
  /**
@@ -8704,16 +8461,18 @@
8704
8461
  wrapper.reject = reject;
8705
8462
  });
8706
8463
  Object.assign(promise, wrapper);
8707
- promise.then(function (v) {
8464
+ // This `then` only mirrors settlement into the state flags. It must NOT
8465
+ // rethrow on rejection: the derived promise is discarded, so rethrowing would
8466
+ // surface as an unhandled rejection whenever the promise is rejected. The real
8467
+ // consumer still awaits `promise` itself, which rejects normally.
8468
+ promise.then(function () {
8708
8469
  promise.isResolved = true;
8709
8470
  promise.isPending = false;
8710
8471
  promise.isRejected = false;
8711
- return v;
8712
- }, function (e) {
8472
+ }, function () {
8713
8473
  promise.isResolved = false;
8714
8474
  promise.isPending = false;
8715
8475
  promise.isRejected = true;
8716
- throw e;
8717
8476
  });
8718
8477
  return promise;
8719
8478
  }
@@ -8721,13 +8480,16 @@
8721
8480
  function urlError() {
8722
8481
  throw new Error('A "url" property or function must be specified');
8723
8482
  }
8724
- // Wrap an optional error callback with a fallback error event.
8725
- function wrapError(model, options) {
8483
+ // Wrap an optional error callback with a fallback error event. When a
8484
+ // `promise` is supplied (the `{ promise: true }` fetch/save path), the error is
8485
+ // also forwarded to `promise.reject` so the returned promise settles on failure.
8486
+ function wrapError(model, options, promise) {
8726
8487
  const error = options.error;
8727
8488
  options.error = function (resp) {
8728
8489
  if (error)
8729
8490
  error.call(options.context, model, resp, options);
8730
8491
  model.trigger('error', model, resp, options);
8492
+ promise && promise.reject && promise.reject(resp);
8731
8493
  };
8732
8494
  }
8733
8495
  // Map from CRUD to HTTP for our default `sync` implementation.
@@ -8738,8 +8500,44 @@
8738
8500
  delete: 'DELETE',
8739
8501
  read: 'GET',
8740
8502
  };
8503
+ // Tracks the classes we've already warned about, so the `browserStorage`
8504
+ // deprecation notice is logged at most once per class rather than once per
8505
+ // instance (a collection can resolve storage once per contained model).
8506
+ const warnedBrowserStorage = new WeakSet();
8507
+ /**
8508
+ * Emit a one-time-per-class deprecation warning nudging downstream code from
8509
+ * the `browserStorage` alias to the canonical `storage` accessor.
8510
+ */
8511
+ function warnBrowserStorageDeprecation(obj) {
8512
+ const ctor = obj?.constructor;
8513
+ if (!ctor || warnedBrowserStorage.has(ctor))
8514
+ return;
8515
+ warnedBrowserStorage.add(ctor);
8516
+ const name = ctor.name;
8517
+ console.warn(`Skeletor: \`browserStorage\` is deprecated and will be removed in a future major version; ` +
8518
+ `use \`storage\` instead${name ? ` (on \`${name}\`)` : ''}.`);
8519
+ }
8520
+ /**
8521
+ * Return the PersistentStorage instance configured on `obj`, checking both
8522
+ * the canonical `storage` accessor and the deprecated `browserStorage` alias
8523
+ * so that subclasses that still override `get browserStorage()` continue to work.
8524
+ * @public
8525
+ */
8526
+ function getStorage(obj) {
8527
+ if (!obj)
8528
+ return undefined;
8529
+ const storage = result(obj, 'storage');
8530
+ if (storage != null)
8531
+ return storage;
8532
+ // Fall back to the deprecated alias; warn only when it actually supplies the
8533
+ // store, so storage-less models/collections don't trip the notice.
8534
+ const legacy = result(obj, 'browserStorage');
8535
+ if (legacy != null)
8536
+ warnBrowserStorageDeprecation(obj);
8537
+ return legacy;
8538
+ }
8741
8539
  function getSyncMethod(model) {
8742
- const store = result(model, 'browserStorage') || result(model.collection, 'browserStorage');
8540
+ const store = getStorage(model) || getStorage(model.collection);
8743
8541
  return store ? store.sync() : sync;
8744
8542
  }
8745
8543
  /**
@@ -8789,15 +8587,56 @@
8789
8587
  localForage.defineDriver(memoryDriver);
8790
8588
  localforageSetitemsExports.extendPrototype(localForage);
8791
8589
  extendPrototype(localForage);
8590
+ // Every storage instance is registered with a WeakRef so that flushAll() can
8591
+ // reach pending writes without keeping instances alive. There's no leak and no
8592
+ // lifecycle hook to maintain: an instance is collected once its owning model or
8593
+ // collection is gone, at which point nothing is writing through it anyway.
8594
+ // Models with a pending debounced save stay reachable via the autosync `pending`
8595
+ // map until the timer fires, so flushAll() always reaches in-flight writes.
8596
+ const weakInstances = new Set();
8597
+ // Tracks which instances already have a WeakRef in `weakInstances`, so repeated
8598
+ // `storage =` assignments (or a store shared across models) don't register the
8599
+ // same instance twice and make flushAll() flush it more than once.
8600
+ const registered = new WeakSet();
8792
8601
  /**
8793
8602
  * @public
8794
8603
  */
8795
- class BrowserStorage {
8604
+ class PersistentStorage {
8605
+ /** Register a storage instance with a weak reference. @public */
8606
+ static register(instance) {
8607
+ if (registered.has(instance))
8608
+ return;
8609
+ registered.add(instance);
8610
+ weakInstances.add(new WeakRef(instance));
8611
+ }
8612
+ /**
8613
+ * Flush the debounced write buffer of every registered PersistentStorage
8614
+ * instance. Called automatically on pagehide/visibilitychange when autoSync
8615
+ * is in use; can also be called manually.
8616
+ * @public
8617
+ */
8618
+ static flushAll() {
8619
+ for (const ref of weakInstances) {
8620
+ const instance = ref.deref();
8621
+ if (!instance) {
8622
+ weakInstances.delete(ref);
8623
+ }
8624
+ else {
8625
+ instance.flush();
8626
+ }
8627
+ }
8628
+ }
8796
8629
  constructor(id, type, batchedWrites = false) {
8797
- if (type === 'local' && !window.localStorage) {
8630
+ // Set once `storeInitialized` resolves. Lets `sync()` skip awaiting it on the
8631
+ // hot path so a save buffers/issues its write *synchronously*, which is what
8632
+ // makes the synchronous unload flush (`flushPending` -> `flushAll`) able to
8633
+ // push a pending write out before the page is torn down.
8634
+ this.storeReady = false;
8635
+ this.name = id;
8636
+ if (type === 'local' && typeof window !== 'undefined' && !window.localStorage) {
8798
8637
  throw new Error('Skeletor.storage: Environment does not support localStorage.');
8799
8638
  }
8800
- else if (type === 'session' && !window.sessionStorage) {
8639
+ else if (type === 'session' && typeof window !== 'undefined' && !window.sessionStorage) {
8801
8640
  throw new Error('Skeletor.storage: Environment does not support sessionStorage.');
8802
8641
  }
8803
8642
  if (isString(type)) {
@@ -8812,10 +8651,13 @@
8812
8651
  }
8813
8652
  this.storeInitialized = Promise.resolve();
8814
8653
  }
8815
- this.name = id;
8654
+ // Flip the synchronous-readiness flag once init settles. Callers that await
8655
+ // `storeInitialized` directly still see any rejection; this branch only
8656
+ // exists to set the flag and must not raise an unhandled rejection.
8657
+ this.storeInitialized.then(() => (this.storeReady = true)).catch(() => { });
8816
8658
  }
8817
8659
  /**
8818
- * @param type - The storage type: 'local', 'session', 'indexed', or 'in_memory'
8660
+ * @param type - The storage type: 'local', 'session', 'indexed', 'node', or 'in_memory'
8819
8661
  * @param batchedWrites - Whether to enable batched writes
8820
8662
  */
8821
8663
  async initStore(type, batchedWrites) {
@@ -8828,6 +8670,16 @@
8828
8670
  else if (type === 'in_memory') {
8829
8671
  await localForage.config({ 'driver': IN_MEMORY });
8830
8672
  }
8673
+ else if (type === 'node') {
8674
+ const { NodeSQLiteStorage } = await import('./drivers/nodeSQLiteStorage');
8675
+ this.store = new NodeSQLiteStorage(this.name);
8676
+ if (batchedWrites) {
8677
+ this.store.debouncedSetItems = mergebounce((items) => this.store.setItems(items), 50, {
8678
+ 'promise': true,
8679
+ });
8680
+ }
8681
+ return;
8682
+ }
8831
8683
  else if (type !== 'indexed') {
8832
8684
  throw new Error('Skeletor.storage: No storage type was specified');
8833
8685
  }
@@ -8844,6 +8696,7 @@
8844
8696
  }
8845
8697
  }
8846
8698
  async clear() {
8699
+ await this.storeInitialized;
8847
8700
  await this.store.removeItem(this.name).catch((e) => console.error(e));
8848
8701
  const re = new RegExp(`^${this.name}-`);
8849
8702
  const keys = await this.store.keys();
@@ -8858,12 +8711,16 @@
8858
8711
  // We get the collection (and if necessary the model attribute.
8859
8712
  // Waiting for storeInitialized will cause another iteration of
8860
8713
  // the event loop, after which the collection reference will
8861
- // be removed from the model.
8862
- const collection = model.collection;
8714
+ // be removed from the model. `options.collection` lets a deferred
8715
+ // delete (sequenced behind an in-flight auto-save by Model.destroy)
8716
+ // supply the collection captured before its optimistic removal.
8717
+ const collection = options.collection ?? model.collection;
8863
8718
  if (['patch', 'update'].includes(method)) {
8864
8719
  new_attributes = cloneDeep(model.attributes);
8865
8720
  }
8866
- await that.storeInitialized;
8721
+ // Skip `await` if not necessary to allow for sync flushing
8722
+ if (!that.storeReady)
8723
+ await that.storeInitialized;
8867
8724
  try {
8868
8725
  const original_attributes = model.attributes;
8869
8726
  switch (method) {
@@ -9018,8 +8875,8 @@
9018
8875
  return this.name + '-' + id;
9019
8876
  }
9020
8877
  }
9021
- BrowserStorage.sessionStorageInitialized = localForage.defineDriver(sessionStorageWrapper);
9022
- BrowserStorage.localForage = localForage;
8878
+ PersistentStorage.sessionStorageInitialized = localForage.defineDriver(sessionStorageWrapper);
8879
+ PersistentStorage.localForage = localForage;
9023
8880
 
9024
8881
  /** Used to compose bitmasks for cloning. */
9025
8882
  var CLONE_SYMBOLS_FLAG$1 = 4;
@@ -9169,7 +9026,7 @@
9169
9026
  * @name has
9170
9027
  * @memberOf SetCache
9171
9028
  * @param {*} value The value to search for.
9172
- * @returns {number} Returns `true` if `value` is found, else `false`.
9029
+ * @returns {boolean} Returns `true` if `value` is found, else `false`.
9173
9030
  */
9174
9031
  function setCacheHas(value) {
9175
9032
  return this.__data__.has(value);
@@ -9452,10 +9309,10 @@
9452
9309
  var COMPARE_PARTIAL_FLAG$3 = 1;
9453
9310
 
9454
9311
  /** Used for built-in method references. */
9455
- var objectProto$5 = Object.prototype;
9312
+ var objectProto$6 = Object.prototype;
9456
9313
 
9457
9314
  /** Used to check objects for own properties. */
9458
- var hasOwnProperty$4 = objectProto$5.hasOwnProperty;
9315
+ var hasOwnProperty$5 = objectProto$6.hasOwnProperty;
9459
9316
 
9460
9317
  /**
9461
9318
  * A specialized version of `baseIsEqualDeep` for objects with support for
@@ -9483,7 +9340,7 @@
9483
9340
  var index = objLength;
9484
9341
  while (index--) {
9485
9342
  var key = objProps[index];
9486
- if (!(isPartial ? key in other : hasOwnProperty$4.call(other, key))) {
9343
+ if (!(isPartial ? key in other : hasOwnProperty$5.call(other, key))) {
9487
9344
  return false;
9488
9345
  }
9489
9346
  }
@@ -9544,10 +9401,10 @@
9544
9401
  objectTag = '[object Object]';
9545
9402
 
9546
9403
  /** Used for built-in method references. */
9547
- var objectProto$4 = Object.prototype;
9404
+ var objectProto$5 = Object.prototype;
9548
9405
 
9549
9406
  /** Used to check objects for own properties. */
9550
- var hasOwnProperty$3 = objectProto$4.hasOwnProperty;
9407
+ var hasOwnProperty$4 = objectProto$5.hasOwnProperty;
9551
9408
 
9552
9409
  /**
9553
9410
  * A specialized version of `baseIsEqual` for arrays and objects which performs
@@ -9590,8 +9447,8 @@
9590
9447
  : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
9591
9448
  }
9592
9449
  if (!(bitmask & COMPARE_PARTIAL_FLAG$2)) {
9593
- var objIsWrapped = objIsObj && hasOwnProperty$3.call(object, '__wrapped__'),
9594
- othIsWrapped = othIsObj && hasOwnProperty$3.call(other, '__wrapped__');
9450
+ var objIsWrapped = objIsObj && hasOwnProperty$4.call(object, '__wrapped__'),
9451
+ othIsWrapped = othIsObj && hasOwnProperty$4.call(other, '__wrapped__');
9595
9452
 
9596
9453
  if (objIsWrapped || othIsWrapped) {
9597
9454
  var objUnwrapped = objIsWrapped ? object.value() : object,
@@ -9965,10 +9822,10 @@
9965
9822
  }
9966
9823
 
9967
9824
  /** Used for built-in method references. */
9968
- var objectProto$3 = Object.prototype;
9825
+ var objectProto$4 = Object.prototype;
9969
9826
 
9970
9827
  /** Used to check objects for own properties. */
9971
- var hasOwnProperty$2 = objectProto$3.hasOwnProperty;
9828
+ var hasOwnProperty$3 = objectProto$4.hasOwnProperty;
9972
9829
 
9973
9830
  /**
9974
9831
  * Creates an object composed of keys generated from the results of running
@@ -9993,7 +9850,7 @@
9993
9850
  * // => { '3': 2, '5': 1 }
9994
9851
  */
9995
9852
  var countBy = createAggregator(function(result, value, key) {
9996
- if (hasOwnProperty$2.call(result, key)) {
9853
+ if (hasOwnProperty$3.call(result, key)) {
9997
9854
  ++result[key];
9998
9855
  } else {
9999
9856
  baseAssignValue(result, key, 1);
@@ -10001,10 +9858,10 @@
10001
9858
  });
10002
9859
 
10003
9860
  /** Used for built-in method references. */
10004
- var objectProto$2 = Object.prototype;
9861
+ var objectProto$3 = Object.prototype;
10005
9862
 
10006
9863
  /** Used to check objects for own properties. */
10007
- var hasOwnProperty$1 = objectProto$2.hasOwnProperty;
9864
+ var hasOwnProperty$2 = objectProto$3.hasOwnProperty;
10008
9865
 
10009
9866
  /**
10010
9867
  * Creates an object composed of keys generated from the results of running
@@ -10030,7 +9887,7 @@
10030
9887
  * // => { '3': ['one', 'two'], '5': ['three'] }
10031
9888
  */
10032
9889
  var groupBy = createAggregator(function(result, value, key) {
10033
- if (hasOwnProperty$1.call(result, key)) {
9890
+ if (hasOwnProperty$2.call(result, key)) {
10034
9891
  result[key].push(value);
10035
9892
  } else {
10036
9893
  baseAssignValue(result, key, [value]);
@@ -10247,7 +10104,7 @@
10247
10104
  if (isArray(iteratee)) {
10248
10105
  return function(value) {
10249
10106
  return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
10250
- }
10107
+ };
10251
10108
  }
10252
10109
  return iteratee;
10253
10110
  });
@@ -10312,11 +10169,130 @@
10312
10169
  return baseOrderBy(collection, baseFlatten(iteratees), []);
10313
10170
  });
10314
10171
 
10172
+ const pending = new Map();
10173
+ const inFlight = new Set();
10174
+ // Per-object view of `inFlight`, so a caller (notably `Model.destroy`) can
10175
+ // await the saves for a single object without blocking on unrelated writes.
10176
+ const inFlightByObj = new Map();
10177
+ let unloadListenerAttached = false;
10178
+ /**
10179
+ * Execute a save `run` now and track the resulting promise as in-flight until
10180
+ * it settles, both globally (`inFlight`) and per object (`inFlightByObj`), so
10181
+ * `flushPending({ wait: true })` can await every save and `Model.destroy` can
10182
+ * await just its own.
10183
+ *
10184
+ * @internal
10185
+ * @param obj - The owning model/collection (or `null` when the save isn't tied to one).
10186
+ * A rejection is logged and re-surfaced on `obj`'s `error` event.
10187
+ * Called when a debounce timer fires or a flush forces it.
10188
+ */
10189
+ function fireRun(obj, run) {
10190
+ const p = Promise.resolve(run()).catch((e) => {
10191
+ console.error('Skeletor autoSync save error:', e);
10192
+ // Surface failures that bypassed `options.error` on the model's `error` event,
10193
+ // the same channel storage-layer failures already use. Storage saves route
10194
+ // errors through `options.error` and then resolve, so they never reach this
10195
+ // catch and won't double-emit.
10196
+ obj?.trigger?.('error', obj, e);
10197
+ });
10198
+ inFlight.add(p);
10199
+ let perObj;
10200
+ if (obj) {
10201
+ perObj = inFlightByObj.get(obj);
10202
+ if (!perObj) {
10203
+ perObj = new Set();
10204
+ inFlightByObj.set(obj, perObj);
10205
+ }
10206
+ perObj.add(p);
10207
+ }
10208
+ p.finally(() => {
10209
+ inFlight.delete(p);
10210
+ if (perObj) {
10211
+ perObj.delete(p);
10212
+ if (perObj.size === 0)
10213
+ inFlightByObj.delete(obj);
10214
+ }
10215
+ });
10216
+ }
10217
+ /**
10218
+ * Schedule a debounced auto-save for `obj`. Replaces any pending schedule
10219
+ * for the same object.
10220
+ * @internal
10221
+ */
10222
+ function scheduleAutoSave(obj, run, delay) {
10223
+ const existing = pending.get(obj);
10224
+ if (existing)
10225
+ clearTimeout(existing.timerId);
10226
+ const timerId = setTimeout(() => {
10227
+ pending.delete(obj);
10228
+ fireRun(obj, run);
10229
+ }, delay);
10230
+ pending.set(obj, { timerId, run });
10231
+ }
10232
+ /**
10233
+ * Cancel any pending auto-save for `obj`.
10234
+ *
10235
+ * This only stops a *pending* (not-yet-fired) debounce timer. A save whose
10236
+ * timer has already fired is in flight and beyond cancellation — sequence
10237
+ * against it with {@link awaitInFlightSaves} instead.
10238
+ * @internal
10239
+ */
10240
+ function cancelAutoSave(obj) {
10241
+ const existing = pending.get(obj);
10242
+ if (existing) {
10243
+ clearTimeout(existing.timerId);
10244
+ pending.delete(obj);
10245
+ }
10246
+ }
10247
+ /**
10248
+ * Return a promise that settles once every in-flight auto-save for `obj` has
10249
+ * completed, or `null` when none are in flight. `Model.destroy` uses this to
10250
+ * sequence its delete after a save that has already fired, so a late write
10251
+ * cannot land after the delete and resurrect the record.
10252
+ * @internal
10253
+ */
10254
+ function awaitInFlightSaves(obj) {
10255
+ const set = inFlightByObj.get(obj);
10256
+ if (!set || set.size === 0)
10257
+ return null;
10258
+ return Promise.all([...set]).then(() => undefined);
10259
+ }
10260
+ function flushPending({ storage, wait = false, } = {}) {
10261
+ for (const [obj, { timerId, run }] of pending.entries()) {
10262
+ clearTimeout(timerId);
10263
+ fireRun(obj, run);
10264
+ }
10265
+ pending.clear();
10266
+ if (storage)
10267
+ storage.flushAll();
10268
+ if (wait)
10269
+ return Promise.all([...inFlight]).then(() => undefined);
10270
+ }
10271
+ /**
10272
+ * Lazily attach pagehide/visibilitychange listeners in browser environments
10273
+ * to flush pending writes when the page is hidden/unloading. This is a
10274
+ * best-effort durability measure: the flush initiates writes synchronously but
10275
+ * cannot guarantee an asynchronous backend finishes persisting them before the
10276
+ * page goes away. Called at most once.
10277
+ * @internal
10278
+ */
10279
+ function ensureUnloadListener(storage) {
10280
+ if (unloadListenerAttached || typeof window === 'undefined')
10281
+ return;
10282
+ unloadListenerAttached = true;
10283
+ const flush = () => flushPending({ storage });
10284
+ window.addEventListener('pagehide', flush);
10285
+ window.addEventListener('visibilitychange', () => {
10286
+ if (document.visibilityState === 'hidden')
10287
+ flush();
10288
+ });
10289
+ }
10290
+
10315
10291
  /** Used for built-in method references. */
10316
- var objectProto$1 = Object.prototype;
10292
+ var objectProto$2 = Object.prototype;
10317
10293
 
10318
10294
  /** Used to check objects for own properties. */
10319
- var hasOwnProperty = objectProto$1.hasOwnProperty;
10295
+ var hasOwnProperty$1 = objectProto$2.hasOwnProperty;
10320
10296
 
10321
10297
  /**
10322
10298
  * Assigns own and inherited enumerable string keyed properties of source
@@ -10361,7 +10337,7 @@
10361
10337
  var value = object[key];
10362
10338
 
10363
10339
  if (value === undefined ||
10364
- (eq(value, objectProto$1[key]) && !hasOwnProperty.call(object, key))) {
10340
+ (eq(value, objectProto$2[key]) && !hasOwnProperty$1.call(object, key))) {
10365
10341
  object[key] = source[key];
10366
10342
  }
10367
10343
  }
@@ -10445,14 +10421,14 @@
10445
10421
  }
10446
10422
 
10447
10423
  /** Used for built-in method references. */
10448
- var objectProto = Object.prototype;
10424
+ var objectProto$1 = Object.prototype;
10449
10425
 
10450
10426
  /**
10451
10427
  * Used to resolve the
10452
10428
  * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
10453
10429
  * of values.
10454
10430
  */
10455
- var nativeObjectToString = objectProto.toString;
10431
+ var nativeObjectToString = objectProto$1.toString;
10456
10432
 
10457
10433
  /**
10458
10434
  * Creates an object composed of the inverted keys and values of `object`.
@@ -10623,6 +10599,12 @@
10623
10599
  return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
10624
10600
  }
10625
10601
 
10602
+ /** Used for built-in method references. */
10603
+ var objectProto = Object.prototype;
10604
+
10605
+ /** Used to check objects for own properties. */
10606
+ var hasOwnProperty = objectProto.hasOwnProperty;
10607
+
10626
10608
  /**
10627
10609
  * The base implementation of `_.unset`.
10628
10610
  *
@@ -10633,8 +10615,34 @@
10633
10615
  */
10634
10616
  function baseUnset(object, path) {
10635
10617
  path = castPath(path, object);
10636
- object = parent(object, path);
10637
- return object == null || delete object[toKey(last(path))];
10618
+
10619
+ // Prevent prototype pollution:
10620
+ // https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg
10621
+ // https://github.com/lodash/lodash/security/advisories/GHSA-f23m-r3pf-42rh
10622
+ var index = -1,
10623
+ length = path.length;
10624
+
10625
+ if (!length) {
10626
+ return true;
10627
+ }
10628
+
10629
+ while (++index < length) {
10630
+ var key = toKey(path[index]);
10631
+
10632
+ // Always block "__proto__" anywhere in the path if it's not expected
10633
+ if (key === '__proto__' && !hasOwnProperty.call(object, '__proto__')) {
10634
+ return false;
10635
+ }
10636
+
10637
+ // Block constructor/prototype as non-terminal traversal keys to prevent
10638
+ // escaping the object graph into built-in constructors and prototypes.
10639
+ if ((key === 'constructor' || key === 'prototype') && index < length - 1) {
10640
+ return false;
10641
+ }
10642
+ }
10643
+
10644
+ var obj = parent(object, path);
10645
+ return obj == null || delete obj[toKey(last(path))];
10638
10646
  }
10639
10647
 
10640
10648
  /**
@@ -10832,6 +10840,7 @@
10832
10840
  return object == null ? {} : basePick(object, paths);
10833
10841
  });
10834
10842
 
10843
+ var _Model_instances, _Model_computedCache, _Model_computedDefs, _Model_state, _Model_hydrate, _Model_doAutoSave, _Model_updateComputed, _Model_initComputed;
10835
10844
  /**
10836
10845
  * @public
10837
10846
  * **Models** are the basic data object in the framework --
@@ -10846,6 +10855,10 @@
10846
10855
  */
10847
10856
  constructor(attributes, options) {
10848
10857
  super();
10858
+ _Model_instances.add(this);
10859
+ _Model_computedCache.set(this, void 0);
10860
+ _Model_computedDefs.set(this, void 0);
10861
+ _Model_state.set(this, 'constructing');
10849
10862
  this._changing = false;
10850
10863
  this._pending = false;
10851
10864
  this._url = '';
@@ -10863,15 +10876,74 @@
10863
10876
  const default_attrs = result(this, 'defaults');
10864
10877
  attrs = defaults(Object.assign({}, default_attrs, attrs), default_attrs);
10865
10878
  this.set(attrs, options);
10879
+ __classPrivateFieldGet(this, _Model_instances, "m", _Model_initComputed).call(this);
10880
+ this.attrs = new Proxy(this.attributes, {
10881
+ get: (_target, key) => {
10882
+ if (typeof key !== 'symbol' && __classPrivateFieldGet(this, _Model_computedCache, "f") && key in __classPrivateFieldGet(this, _Model_computedCache, "f")) {
10883
+ return __classPrivateFieldGet(this, _Model_computedCache, "f")[key];
10884
+ }
10885
+ return this.attributes[key];
10886
+ },
10887
+ set: (_target, key, value) => {
10888
+ this.set(key, value);
10889
+ return true;
10890
+ },
10891
+ });
10866
10892
  this.initialize.apply(this, arguments);
10867
10893
  // Reset changed after initial set
10868
10894
  this.changed = {};
10895
+ // When autoSync is on, `initialized` is always a Promise so callers can
10896
+ // uniformly `await model.initialized`. It only hydrates from storage when
10897
+ // there's something to load (storage configured and the model isn't new);
10898
+ // otherwise it's already ready and resolves immediately.
10899
+ if (this.autoSync) {
10900
+ if (getStorage(this) && !this.isNew()) {
10901
+ __classPrivateFieldSet(this, _Model_state, 'hydrating', "f");
10902
+ this.initialized = __classPrivateFieldGet(this, _Model_instances, "m", _Model_hydrate).call(this);
10903
+ }
10904
+ else {
10905
+ __classPrivateFieldSet(this, _Model_state, 'ready', "f");
10906
+ this.initialized = Promise.resolve();
10907
+ }
10908
+ }
10909
+ else {
10910
+ __classPrivateFieldSet(this, _Model_state, 'ready', "f");
10911
+ }
10912
+ }
10913
+ /**
10914
+ * The canonical storage accessor. Set to a `PersistentStorage` instance
10915
+ * to enable local persistence for this model.
10916
+ */
10917
+ get storage() {
10918
+ return this._storage;
10869
10919
  }
10870
- set browserStorage(storage) {
10871
- this._browserStorage = storage;
10920
+ set storage(s) {
10921
+ this._storage = s;
10922
+ PersistentStorage.register(s);
10872
10923
  }
10924
+ /**
10925
+ * @deprecated Use `storage` instead.
10926
+ */
10873
10927
  get browserStorage() {
10874
- return this._browserStorage;
10928
+ return this._storage;
10929
+ }
10930
+ set browserStorage(s) {
10931
+ warnBrowserStorageDeprecation(this);
10932
+ this.storage = s;
10933
+ }
10934
+ /**
10935
+ * Override to enable automatic persistence. When true, any `set()` call
10936
+ * that changes attributes will schedule a debounced save to `storage`, and
10937
+ * the model will auto-hydrate from storage on construction.
10938
+ */
10939
+ get autoSync() {
10940
+ return false;
10941
+ }
10942
+ /**
10943
+ * Debounce delay (ms) for auto-save writes. Override to tune.
10944
+ */
10945
+ get autoSyncDelay() {
10946
+ return 100;
10875
10947
  }
10876
10948
  /**
10877
10949
  * The default name for the JSON `id` attribute is `"id"`. MongoDB and
@@ -10907,6 +10979,17 @@
10907
10979
  defaults() {
10908
10980
  return {};
10909
10981
  }
10982
+ /**
10983
+ * Declare computed properties. Override in subclasses to define properties
10984
+ * that derive their value from other attributes. Each entry specifies the
10985
+ * attribute keys it depends on (`deps`) and a function (`fn`) that receives
10986
+ * the model and returns the computed value. The value is cached and
10987
+ * recalculated automatically when any dep changes, firing a `change:key`
10988
+ * event.
10989
+ */
10990
+ get computed() {
10991
+ return {};
10992
+ }
10910
10993
  /**
10911
10994
  * Return a copy of the model's `attributes` object.
10912
10995
  */
@@ -10920,9 +11003,12 @@
10920
11003
  return getSyncMethod(model)(method, model, options);
10921
11004
  }
10922
11005
  /**
10923
- * Get the value of an attribute.
11006
+ * Get the value of an attribute, or a computed property.
10924
11007
  */
10925
11008
  get(attr) {
11009
+ if (__classPrivateFieldGet(this, _Model_computedCache, "f") && attr in __classPrivateFieldGet(this, _Model_computedCache, "f")) {
11010
+ return __classPrivateFieldGet(this, _Model_computedCache, "f")[attr];
11011
+ }
10926
11012
  return this.attributes[attr];
10927
11013
  }
10928
11014
  keys() {
@@ -10987,6 +11073,11 @@
10987
11073
  attrs[key] = val;
10988
11074
  }
10989
11075
  options = options || {};
11076
+ // Guard must come after arg normalization: when called as set(obj, opts),
11077
+ // fromStorage lives in `val` (second arg), not `options` (third arg).
11078
+ if (this.autoSync && __classPrivateFieldGet(this, _Model_state, "f") === 'hydrating' && !options.fromStorage) {
11079
+ throw new Error(`Skeletor: set() called on an autoSync model before initialized resolved. Await model.initialized first.`);
11080
+ }
10990
11081
  // Run validation.
10991
11082
  if (!this._validate(attrs, options))
10992
11083
  return null;
@@ -11027,6 +11118,14 @@
11027
11118
  this.trigger('change:' + changes[i], this, current[changes[i]], options);
11028
11119
  }
11029
11120
  }
11121
+ // Recalculate computed properties whose deps changed.
11122
+ if (changes.length && __classPrivateFieldGet(this, _Model_computedDefs, "f")) {
11123
+ for (const [key, def] of Object.entries(__classPrivateFieldGet(this, _Model_computedDefs, "f"))) {
11124
+ if (def.deps.some((dep) => changes.includes(dep))) {
11125
+ __classPrivateFieldGet(this, _Model_instances, "m", _Model_updateComputed).call(this, key, def, silent, options);
11126
+ }
11127
+ }
11128
+ }
11030
11129
  if (changing)
11031
11130
  return this;
11032
11131
  if (!silent) {
@@ -11040,6 +11139,17 @@
11040
11139
  }
11041
11140
  this._pending = false;
11042
11141
  this._changing = false;
11142
+ // Auto-save: schedule a debounced write when autoSync is on and there
11143
+ // were actual changes that originated from application code (not a
11144
+ // storage read or an explicit noAutoSave call).
11145
+ if (__classPrivateFieldGet(this, _Model_state, "f") === 'ready' &&
11146
+ this.autoSync &&
11147
+ getStorage(this) &&
11148
+ changes.length &&
11149
+ !options.fromStorage &&
11150
+ !options.noAutoSave) {
11151
+ scheduleAutoSave(this, () => __classPrivateFieldGet(this, _Model_instances, "m", _Model_doAutoSave).call(this), this.autoSyncDelay);
11152
+ }
11043
11153
  return this;
11044
11154
  }
11045
11155
  /**
@@ -11114,16 +11224,48 @@
11114
11224
  fetch(options = {}) {
11115
11225
  options = Object.assign({ parse: true }, options);
11116
11226
  const success = options.success;
11227
+ const promise = options.promise ? getResolveablePromise() : undefined;
11228
+ // Tracks whether sync invoked one of the callbacks. A sync may instead
11229
+ // settle its returned promise; the `.then`/`.catch` below bridges that to
11230
+ // the callbacks so the fetch promise never hangs. The flag is set
11231
+ // synchronously inside each callback (before sync's promise resolves), so
11232
+ // it's reliable by the time those handlers run.
11233
+ let settled = false;
11117
11234
  options.success = (resp) => {
11235
+ settled = true;
11118
11236
  const serverAttrs = options.parse ? this.parse(resp, options) : resp;
11119
- if (!this.set(serverAttrs, options))
11237
+ // fromStorage prevents the set() from triggering auto-save on reads
11238
+ if (!this.set(serverAttrs, Object.assign({}, options, { fromStorage: true })))
11120
11239
  return false;
11121
11240
  if (success)
11122
11241
  success.call(options.context, this, resp, options);
11123
11242
  this.trigger('sync', this, resp, options);
11243
+ promise && promise.resolve(resp);
11124
11244
  };
11125
- wrapError(this, options);
11126
- return this.sync('read', this, options);
11245
+ wrapError(this, options, promise);
11246
+ if (promise) {
11247
+ const onError = options.error;
11248
+ options.error = (resp) => {
11249
+ settled = true;
11250
+ onError(resp);
11251
+ };
11252
+ }
11253
+ const result = this.sync('read', this, options);
11254
+ if (promise) {
11255
+ Promise.resolve(result).then(
11256
+ // A sync that resolves its promise without invoking options.success:
11257
+ // treat the resolved value as the response, so the model is still
11258
+ // merged and the promise settles instead of hanging.
11259
+ (value) => {
11260
+ if (!settled)
11261
+ options.success(value);
11262
+ },
11263
+ // A sync that rejects instead of invoking options.error; settling
11264
+ // twice is a harmless no-op.
11265
+ (e) => promise.reject(e));
11266
+ return promise;
11267
+ }
11268
+ return result;
11127
11269
  }
11128
11270
  /**
11129
11271
  * Set a hash of model attributes, and sync the model to the server.
@@ -11200,6 +11342,7 @@
11200
11342
  * If `wait: true` is passed, waits for the server to respond before removal.
11201
11343
  */
11202
11344
  destroy(options) {
11345
+ cancelAutoSave(this);
11203
11346
  options = options ? clone(options) : {};
11204
11347
  const success = options.success;
11205
11348
  const wait = options.wait;
@@ -11215,13 +11358,25 @@
11215
11358
  if (!this.isNew())
11216
11359
  this.trigger('sync', this, resp, options);
11217
11360
  };
11361
+ // A debounced auto-save may already have fired and be in flight.
11362
+ // cancelAutoSave() above only stops a *pending* timer, so sequence the
11363
+ // delete after any in-flight save; otherwise the late write could land
11364
+ // after the delete and resurrect the record. Capture the collection now,
11365
+ // the optimistic in-memory removal below nulls `model.collection` before
11366
+ // the deferred sync runs, but the storage layer still needs it to drop
11367
+ // this id from the collection's persisted index.
11368
+ const inFlightSave = awaitInFlightSaves(this);
11369
+ if (inFlightSave && this.collection)
11370
+ options.collection = this.collection;
11218
11371
  let xhr = false;
11219
11372
  if (this.isNew()) {
11220
11373
  defer(options.success);
11221
11374
  }
11222
11375
  else {
11223
11376
  wrapError(this, options);
11224
- xhr = this.sync('delete', this, options);
11377
+ xhr = inFlightSave
11378
+ ? inFlightSave.then(() => this.sync('delete', this, options))
11379
+ : this.sync('delete', this, options);
11225
11380
  }
11226
11381
  if (!wait)
11227
11382
  destroy();
@@ -11269,6 +11424,14 @@
11269
11424
  isValid(options) {
11270
11425
  return this._validate({}, Object.assign({}, options, { validate: true }));
11271
11426
  }
11427
+ subscribe(eventOrCallback, callback, context) {
11428
+ if (typeof eventOrCallback === 'function') {
11429
+ const cb = (model) => eventOrCallback(model, this.changed);
11430
+ this.on('change', cb);
11431
+ return () => this.off('change', cb);
11432
+ }
11433
+ return super.subscribe(eventOrCallback, callback, context);
11434
+ }
11272
11435
  /**
11273
11436
  * Run validation against the next complete set of model attributes,
11274
11437
  * returning `true` if all is well. Otherwise, fire an `"invalid"` event.
@@ -11284,8 +11447,43 @@
11284
11447
  return false;
11285
11448
  }
11286
11449
  }
11450
+ _Model_computedCache = new WeakMap(), _Model_computedDefs = new WeakMap(), _Model_state = new WeakMap(), _Model_instances = new WeakSet(), _Model_hydrate = async function _Model_hydrate() {
11451
+ ensureUnloadListener(PersistentStorage);
11452
+ try {
11453
+ await this.fetch({ fromStorage: true, promise: true });
11454
+ }
11455
+ catch (e) {
11456
+ // 'Record Not Found' is a normal first-run state (nothing stored yet);
11457
+ // keep the initial attributes and resolve. Re-throw anything else.
11458
+ if (e !== 'Record Not Found')
11459
+ throw e;
11460
+ }
11461
+ finally {
11462
+ __classPrivateFieldSet(this, _Model_state, 'ready', "f");
11463
+ }
11464
+ }, _Model_doAutoSave = function _Model_doAutoSave() {
11465
+ return this.save(null, { noAutoSave: true });
11466
+ }, _Model_updateComputed = function _Model_updateComputed(key, def, silent, options) {
11467
+ const newVal = def.fn(this);
11468
+ if (!isEqual(__classPrivateFieldGet(this, _Model_computedCache, "f")[key], newVal)) {
11469
+ __classPrivateFieldGet(this, _Model_computedCache, "f")[key] = newVal;
11470
+ if (!silent) {
11471
+ this.changed[key] = newVal;
11472
+ this.trigger('change:' + key, this, newVal, options);
11473
+ }
11474
+ }
11475
+ }, _Model_initComputed = function _Model_initComputed() {
11476
+ const defs = result(this, 'computed');
11477
+ if (!defs || isEmpty(defs))
11478
+ return;
11479
+ __classPrivateFieldSet(this, _Model_computedDefs, defs, "f");
11480
+ __classPrivateFieldSet(this, _Model_computedCache, {}, "f");
11481
+ for (const [key, def] of Object.entries(defs)) {
11482
+ __classPrivateFieldGet(this, _Model_computedCache, "f")[key] = def.fn(this);
11483
+ }
11484
+ };
11287
11485
 
11288
- var _a;
11486
+ var _Collection_instances, _Collection_hydrate, _a;
11289
11487
  // Default options for `Collection#set`.
11290
11488
  const setOptions = { add: true, remove: true, merge: true };
11291
11489
  const addOptions = { add: true, remove: false };
@@ -11306,6 +11504,7 @@
11306
11504
  */
11307
11505
  constructor(models, options) {
11308
11506
  super();
11507
+ _Collection_instances.add(this);
11309
11508
  this._url = '';
11310
11509
  /**
11311
11510
  * @public
@@ -11323,6 +11522,12 @@
11323
11522
  if (models)
11324
11523
  this.reset(models, Object.assign({ silent: true }, options));
11325
11524
  this[Symbol.iterator] = this.values;
11525
+ // When autoSync is on, `initialized` is always a Promise so callers can
11526
+ // uniformly `await collection.initialized`; it resolves immediately when
11527
+ // there's no storage to hydrate from.
11528
+ if (this.autoSync) {
11529
+ this.initialized = getStorage(this) ? __classPrivateFieldGet(this, _Collection_instances, "m", _Collection_hydrate).call(this) : Promise.resolve();
11530
+ }
11326
11531
  }
11327
11532
  get comparator() {
11328
11533
  return this._comparator;
@@ -11330,11 +11535,40 @@
11330
11535
  set comparator(c) {
11331
11536
  this._comparator = c;
11332
11537
  }
11333
- set browserStorage(storage) {
11334
- this._browserStorage = storage;
11538
+ /**
11539
+ * The canonical storage accessor. Set to a `PersistentStorage` instance
11540
+ * to enable local persistence for this collection.
11541
+ */
11542
+ get storage() {
11543
+ return this._storage;
11544
+ }
11545
+ set storage(s) {
11546
+ this._storage = s;
11547
+ PersistentStorage.register(s);
11335
11548
  }
11549
+ /**
11550
+ * @deprecated Use `storage` instead.
11551
+ */
11336
11552
  get browserStorage() {
11337
- return this._browserStorage;
11553
+ return this._storage;
11554
+ }
11555
+ set browserStorage(s) {
11556
+ warnBrowserStorageDeprecation(this);
11557
+ this.storage = s;
11558
+ }
11559
+ /**
11560
+ * Override to return `true` to automatically load the collection from
11561
+ * storage on construction. Await `initialized` to know when hydration
11562
+ * is complete.
11563
+ *
11564
+ * Note: collection `autoSync` is hydrate-only. Unlike `Model`, it does
11565
+ * **not** schedule auto-saves when the collection changes (`add`/`remove`/
11566
+ * `reset`). Persisting members is each model's responsibility — enable
11567
+ * `autoSync` on the contained model class and every model writes its own
11568
+ * record. A collection-level write would be redundant with that.
11569
+ */
11570
+ get autoSync() {
11571
+ return false;
11338
11572
  }
11339
11573
  /**
11340
11574
  * The default model for a collection is just a **Model**.
@@ -11529,7 +11763,7 @@
11529
11763
  }));
11530
11764
  });
11531
11765
  }));
11532
- await this.browserStorage?.clear();
11766
+ await getStorage(this)?.clear();
11533
11767
  this.reset();
11534
11768
  }
11535
11769
  /**
@@ -11767,17 +12001,47 @@
11767
12001
  const success = options.success;
11768
12002
  // eslint-disable-next-line @typescript-eslint/no-this-alias
11769
12003
  const collection = this;
11770
- const promise = options.promise && getResolveablePromise();
12004
+ const promise = options.promise ? getResolveablePromise() : undefined;
12005
+ // Tracks whether sync invoked one of the callbacks. A sync may instead
12006
+ // settle its returned promise; the `.then`/`.catch` below bridges that to
12007
+ // the callbacks so the fetch promise never hangs. The flag is set
12008
+ // synchronously inside each callback (before sync's promise resolves), so
12009
+ // it's reliable by the time those handlers run.
12010
+ let settled = false;
11771
12011
  options.success = function (resp) {
12012
+ settled = true;
11772
12013
  const method = options.reset ? 'reset' : 'set';
11773
- collection[method](resp, options);
12014
+ // fromStorage prevents individual model set() calls from triggering auto-save on reads
12015
+ collection[method](resp, Object.assign({}, options, { fromStorage: true }));
11774
12016
  if (success)
11775
12017
  success.call(options.context, collection, resp, options);
11776
12018
  promise && promise.resolve();
11777
12019
  collection.trigger('sync', collection, resp, options);
11778
12020
  };
11779
- wrapError(this, options);
11780
- return promise ? promise : this.sync('read', this, options);
12021
+ wrapError(this, options, promise);
12022
+ if (promise) {
12023
+ const onError = options.error;
12024
+ options.error = (resp) => {
12025
+ settled = true;
12026
+ onError(resp);
12027
+ };
12028
+ }
12029
+ const result = this.sync('read', this, options);
12030
+ if (promise) {
12031
+ Promise.resolve(result).then(
12032
+ // A sync that resolves its promise without invoking options.success:
12033
+ // treat the resolved value as the response, so the collection is still
12034
+ // populated and the promise settles instead of hanging.
12035
+ (value) => {
12036
+ if (!settled)
12037
+ options.success(value);
12038
+ },
12039
+ // A sync that rejects instead of invoking options.error; settling
12040
+ // twice is a harmless no-op.
12041
+ (e) => promise.reject(e));
12042
+ return promise;
12043
+ }
12044
+ return result;
11781
12045
  }
11782
12046
  /**
11783
12047
  * Create a new instance of a model in this collection. Add the model to the
@@ -11821,6 +12085,14 @@
11821
12085
  return preparedModel;
11822
12086
  }
11823
12087
  }
12088
+ subscribe(eventOrCallback, callback, context) {
12089
+ if (typeof eventOrCallback === 'function') {
12090
+ const cb = () => eventOrCallback(this);
12091
+ this.on('update reset sort', cb);
12092
+ return () => this.off('update reset sort', cb);
12093
+ }
12094
+ return super.subscribe(eventOrCallback, callback, context);
12095
+ }
11824
12096
  /**
11825
12097
  * **parse** converts a response into a list of models to be added to the
11826
12098
  * collection. The default implementation is just to pass it through.
@@ -11958,7 +12230,12 @@
11958
12230
  this.trigger.apply(this, arguments);
11959
12231
  }
11960
12232
  }
11961
- _a = Symbol.iterator;
12233
+ _Collection_instances = new WeakSet(), _Collection_hydrate = async function _Collection_hydrate() {
12234
+ ensureUnloadListener(PersistentStorage);
12235
+ // findAll() returns [] for an empty store, so a first-run collection
12236
+ // resolves rather than erroring the way a model fetch-by-id would.
12237
+ await this.fetch({ fromStorage: true, promise: true });
12238
+ }, _a = Symbol.iterator;
11962
12239
  // This "enum" defines the three possible kinds of values which can be emitted
11963
12240
  // by a CollectionIterator that correspond to the values(), keys() and entries()
11964
12241
  // methods on Collection, respectively.
@@ -12047,12 +12324,19 @@
12047
12324
  }
12048
12325
  skeletor.noConflict = noConflict;
12049
12326
  root.Skeletor = skeletor;
12327
+ /**
12328
+ * @deprecated Use `PersistentStorage` instead.
12329
+ * @public
12330
+ */
12331
+ const BrowserStorage = PersistentStorage;
12050
12332
 
12051
12333
  exports.BrowserStorage = BrowserStorage;
12052
12334
  exports.Collection = Collection;
12053
12335
  exports.EventEmitter = EventEmitter;
12054
12336
  exports.Model = Model;
12337
+ exports.PersistentStorage = PersistentStorage;
12055
12338
  exports.default = skeletor;
12339
+ exports.getStorage = getStorage;
12056
12340
  exports.noConflict = noConflict;
12057
12341
  exports.sync = sync;
12058
12342