@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.
@@ -1,5 +1,5 @@
1
1
  /** Used for built-in method references. */
2
- var objectProto$l = Object.prototype;
2
+ var objectProto$m = Object.prototype;
3
3
 
4
4
  /**
5
5
  * Checks if `value` is likely a prototype object.
@@ -10,7 +10,7 @@ var objectProto$l = Object.prototype;
10
10
  */
11
11
  function isPrototype(value) {
12
12
  var Ctor = value && value.constructor,
13
- proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$l;
13
+ proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$m;
14
14
 
15
15
  return value === proto;
16
16
  }
@@ -33,10 +33,10 @@ function overArg(func, transform) {
33
33
  var nativeKeys = overArg(Object.keys, Object);
34
34
 
35
35
  /** Used for built-in method references. */
36
- var objectProto$k = Object.prototype;
36
+ var objectProto$l = Object.prototype;
37
37
 
38
38
  /** Used to check objects for own properties. */
39
- var hasOwnProperty$h = objectProto$k.hasOwnProperty;
39
+ var hasOwnProperty$i = objectProto$l.hasOwnProperty;
40
40
 
41
41
  /**
42
42
  * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
@@ -51,7 +51,7 @@ function baseKeys(object) {
51
51
  }
52
52
  var result = [];
53
53
  for (var key in Object(object)) {
54
- if (hasOwnProperty$h.call(object, key) && key != 'constructor') {
54
+ if (hasOwnProperty$i.call(object, key) && key != 'constructor') {
55
55
  result.push(key);
56
56
  }
57
57
  }
@@ -71,17 +71,17 @@ var root$1 = freeGlobal || freeSelf || Function('return this')();
71
71
  var Symbol$1 = root$1.Symbol;
72
72
 
73
73
  /** Used for built-in method references. */
74
- var objectProto$j = Object.prototype;
74
+ var objectProto$k = Object.prototype;
75
75
 
76
76
  /** Used to check objects for own properties. */
77
- var hasOwnProperty$g = objectProto$j.hasOwnProperty;
77
+ var hasOwnProperty$h = objectProto$k.hasOwnProperty;
78
78
 
79
79
  /**
80
80
  * Used to resolve the
81
81
  * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
82
82
  * of values.
83
83
  */
84
- var nativeObjectToString$2 = objectProto$j.toString;
84
+ var nativeObjectToString$2 = objectProto$k.toString;
85
85
 
86
86
  /** Built-in value references. */
87
87
  var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined;
@@ -94,7 +94,7 @@ var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined;
94
94
  * @returns {string} Returns the raw `toStringTag`.
95
95
  */
96
96
  function getRawTag(value) {
97
- var isOwn = hasOwnProperty$g.call(value, symToStringTag$1),
97
+ var isOwn = hasOwnProperty$h.call(value, symToStringTag$1),
98
98
  tag = value[symToStringTag$1];
99
99
 
100
100
  try {
@@ -114,14 +114,14 @@ function getRawTag(value) {
114
114
  }
115
115
 
116
116
  /** Used for built-in method references. */
117
- var objectProto$i = Object.prototype;
117
+ var objectProto$j = Object.prototype;
118
118
 
119
119
  /**
120
120
  * Used to resolve the
121
121
  * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
122
122
  * of values.
123
123
  */
124
- var nativeObjectToString$1 = objectProto$i.toString;
124
+ var nativeObjectToString$1 = objectProto$j.toString;
125
125
 
126
126
  /**
127
127
  * Converts `value` to a string using `Object.prototype.toString`.
@@ -276,17 +276,17 @@ var reIsHostCtor = /^\[object .+?Constructor\]$/;
276
276
 
277
277
  /** Used for built-in method references. */
278
278
  var funcProto$1 = Function.prototype,
279
- objectProto$h = Object.prototype;
279
+ objectProto$i = Object.prototype;
280
280
 
281
281
  /** Used to resolve the decompiled source of functions. */
282
282
  var funcToString$1 = funcProto$1.toString;
283
283
 
284
284
  /** Used to check objects for own properties. */
285
- var hasOwnProperty$f = objectProto$h.hasOwnProperty;
285
+ var hasOwnProperty$g = objectProto$i.hasOwnProperty;
286
286
 
287
287
  /** Used to detect if a method is native. */
288
288
  var reIsNative = RegExp('^' +
289
- funcToString$1.call(hasOwnProperty$f).replace(reRegExpChar, '\\$&')
289
+ funcToString$1.call(hasOwnProperty$g).replace(reRegExpChar, '\\$&')
290
290
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
291
291
  );
292
292
 
@@ -335,16 +335,16 @@ function getNative(object, key) {
335
335
  var DataView = getNative(root$1, 'DataView');
336
336
 
337
337
  /* Built-in method references that are verified to be native. */
338
- var Map = getNative(root$1, 'Map');
338
+ var Map$1 = getNative(root$1, 'Map');
339
339
 
340
340
  /* Built-in method references that are verified to be native. */
341
341
  var Promise$1 = getNative(root$1, 'Promise');
342
342
 
343
343
  /* Built-in method references that are verified to be native. */
344
- var Set = getNative(root$1, 'Set');
344
+ var Set$1 = getNative(root$1, 'Set');
345
345
 
346
346
  /* Built-in method references that are verified to be native. */
347
- var WeakMap = getNative(root$1, 'WeakMap');
347
+ var WeakMap$1 = getNative(root$1, 'WeakMap');
348
348
 
349
349
  /** `Object#toString` result references. */
350
350
  var mapTag$6 = '[object Map]',
@@ -357,10 +357,10 @@ var dataViewTag$4 = '[object DataView]';
357
357
 
358
358
  /** Used to detect maps, sets, and weakmaps. */
359
359
  var dataViewCtorString = toSource(DataView),
360
- mapCtorString = toSource(Map),
360
+ mapCtorString = toSource(Map$1),
361
361
  promiseCtorString = toSource(Promise$1),
362
- setCtorString = toSource(Set),
363
- weakMapCtorString = toSource(WeakMap);
362
+ setCtorString = toSource(Set$1),
363
+ weakMapCtorString = toSource(WeakMap$1);
364
364
 
365
365
  /**
366
366
  * Gets the `toStringTag` of `value`.
@@ -373,10 +373,10 @@ var getTag = baseGetTag;
373
373
 
374
374
  // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
375
375
  if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag$4) ||
376
- (Map && getTag(new Map) != mapTag$6) ||
376
+ (Map$1 && getTag(new Map$1) != mapTag$6) ||
377
377
  (Promise$1 && getTag(Promise$1.resolve()) != promiseTag) ||
378
- (Set && getTag(new Set) != setTag$6) ||
379
- (WeakMap && getTag(new WeakMap) != weakMapTag$2)) {
378
+ (Set$1 && getTag(new Set$1) != setTag$6) ||
379
+ (WeakMap$1 && getTag(new WeakMap$1) != weakMapTag$2)) {
380
380
  getTag = function(value) {
381
381
  var result = baseGetTag(value),
382
382
  Ctor = result == objectTag$4 ? value.constructor : undefined,
@@ -438,13 +438,13 @@ function baseIsArguments(value) {
438
438
  }
439
439
 
440
440
  /** Used for built-in method references. */
441
- var objectProto$g = Object.prototype;
441
+ var objectProto$h = Object.prototype;
442
442
 
443
443
  /** Used to check objects for own properties. */
444
- var hasOwnProperty$e = objectProto$g.hasOwnProperty;
444
+ var hasOwnProperty$f = objectProto$h.hasOwnProperty;
445
445
 
446
446
  /** Built-in value references. */
447
- var propertyIsEnumerable$1 = objectProto$g.propertyIsEnumerable;
447
+ var propertyIsEnumerable$1 = objectProto$h.propertyIsEnumerable;
448
448
 
449
449
  /**
450
450
  * Checks if `value` is likely an `arguments` object.
@@ -465,7 +465,7 @@ var propertyIsEnumerable$1 = objectProto$g.propertyIsEnumerable;
465
465
  * // => false
466
466
  */
467
467
  var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
468
- return isObjectLike(value) && hasOwnProperty$e.call(value, 'callee') &&
468
+ return isObjectLike(value) && hasOwnProperty$f.call(value, 'callee') &&
469
469
  !propertyIsEnumerable$1.call(value, 'callee');
470
470
  };
471
471
 
@@ -730,10 +730,10 @@ var mapTag$4 = '[object Map]',
730
730
  setTag$4 = '[object Set]';
731
731
 
732
732
  /** Used for built-in method references. */
733
- var objectProto$f = Object.prototype;
733
+ var objectProto$g = Object.prototype;
734
734
 
735
735
  /** Used to check objects for own properties. */
736
- var hasOwnProperty$d = objectProto$f.hasOwnProperty;
736
+ var hasOwnProperty$e = objectProto$g.hasOwnProperty;
737
737
 
738
738
  /**
739
739
  * Checks if `value` is an empty object, collection, map, or set.
@@ -785,7 +785,7 @@ function isEmpty(value) {
785
785
  return !baseKeys(value).length;
786
786
  }
787
787
  for (var key in value) {
788
- if (hasOwnProperty$d.call(value, key)) {
788
+ if (hasOwnProperty$e.call(value, key)) {
789
789
  return false;
790
790
  }
791
791
  }
@@ -836,10 +836,10 @@ function isIndex(value, length) {
836
836
  }
837
837
 
838
838
  /** Used for built-in method references. */
839
- var objectProto$e = Object.prototype;
839
+ var objectProto$f = Object.prototype;
840
840
 
841
841
  /** Used to check objects for own properties. */
842
- var hasOwnProperty$c = objectProto$e.hasOwnProperty;
842
+ var hasOwnProperty$d = objectProto$f.hasOwnProperty;
843
843
 
844
844
  /**
845
845
  * Creates an array of the enumerable property names of the array-like `value`.
@@ -859,7 +859,7 @@ function arrayLikeKeys(value, inherited) {
859
859
  length = result.length;
860
860
 
861
861
  for (var key in value) {
862
- if ((inherited || hasOwnProperty$c.call(value, key)) &&
862
+ if ((inherited || hasOwnProperty$d.call(value, key)) &&
863
863
  !(skipIndexes && (
864
864
  // Safari 9 has enumerable `arguments.length` in strict mode.
865
865
  key == 'length' ||
@@ -1002,7 +1002,7 @@ function baseToString(value) {
1002
1002
  * _.toString([1, 2, 3]);
1003
1003
  * // => '1,2,3'
1004
1004
  */
1005
- function toString$2(value) {
1005
+ function toString$1(value) {
1006
1006
  return value == null ? '' : baseToString(value);
1007
1007
  }
1008
1008
 
@@ -1028,7 +1028,7 @@ var idCounter = 0;
1028
1028
  */
1029
1029
  function uniqueId(prefix) {
1030
1030
  var id = ++idCounter;
1031
- return toString$2(prefix) + id;
1031
+ return toString$1(prefix) + id;
1032
1032
  }
1033
1033
 
1034
1034
  /** Used to match a single whitespace character. */
@@ -1624,6 +1624,14 @@ function EventEmitter(Base) {
1624
1624
  eventsApi(triggerApi, this._events, name, undefined, args);
1625
1625
  return this;
1626
1626
  }
1627
+ /**
1628
+ * Subscribe to an event. Returns an unsubscribe function.
1629
+ * Compatible with `useSyncExternalStore` and other store-style APIs.
1630
+ */
1631
+ subscribe(event, callback, context) {
1632
+ this.on(event, callback, context);
1633
+ return () => this.off(event, callback, context);
1634
+ }
1627
1635
  };
1628
1636
  }
1629
1637
  /**
@@ -1631,7 +1639,7 @@ function EventEmitter(Base) {
1631
1639
  */
1632
1640
  const EventEmitterObject = EventEmitter(Object);
1633
1641
 
1634
- /*! *****************************************************************************
1642
+ /******************************************************************************
1635
1643
  Copyright (c) Microsoft Corporation.
1636
1644
 
1637
1645
  Permission to use, copy, modify, and/or distribute this software for any
@@ -1645,7 +1653,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1645
1653
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1646
1654
  PERFORMANCE OF THIS SOFTWARE.
1647
1655
  ***************************************************************************** */
1648
- /* global Reflect, Promise */
1656
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
1649
1657
 
1650
1658
 
1651
1659
  function __values(o) {
@@ -1658,7 +1666,25 @@ function __values(o) {
1658
1666
  }
1659
1667
  };
1660
1668
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
1661
- }
1669
+ }
1670
+
1671
+ function __classPrivateFieldGet(receiver, state, kind, f) {
1672
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
1673
+ 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");
1674
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
1675
+ }
1676
+
1677
+ function __classPrivateFieldSet(receiver, state, value, kind, f) {
1678
+ if (kind === "m") throw new TypeError("Private method is not writable");
1679
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
1680
+ 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");
1681
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
1682
+ }
1683
+
1684
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1685
+ var e = new Error(message);
1686
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1687
+ };
1662
1688
 
1663
1689
  /*!
1664
1690
  MIT License
@@ -1697,7 +1723,7 @@ SOFTWARE.
1697
1723
  * @param parts
1698
1724
  * @param properties
1699
1725
  */
1700
- function createBlob$1(parts, properties) {
1726
+ function createBlob(parts, properties) {
1701
1727
  /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */
1702
1728
  parts = parts || [];
1703
1729
  properties = properties || {};
@@ -1721,12 +1747,12 @@ function createBlob$1(parts, properties) {
1721
1747
  }
1722
1748
  }
1723
1749
 
1724
- var BLOB_TYPE_PREFIX_REGEX$1 = /^~~local_forage_type~([^~]+)~/;
1725
- var SERIALIZED_MARKER_LENGTH$1 = "__lfsc__:" /* SERIALIZED_MARKER */.length;
1726
- var TYPE_SERIALIZED_MARKER_LENGTH$1 = SERIALIZED_MARKER_LENGTH$1 + "arbf" /* TYPE_ARRAYBUFFER */.length;
1750
+ var BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;
1751
+ var SERIALIZED_MARKER_LENGTH = "__lfsc__:" /* SERIALIZED_MARKER */.length;
1752
+ var TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH + "arbf" /* TYPE_ARRAYBUFFER */.length;
1727
1753
  //tslint:disable:no-magic-numbers no-bitwise prefer-switch no-unbound-method
1728
- var toString$1 = Object.prototype.toString;
1729
- function stringToBuffer$1(serializedString) {
1754
+ var toString = Object.prototype.toString;
1755
+ function stringToBuffer(serializedString) {
1730
1756
  // Fill the string into a ArrayBuffer.
1731
1757
  var bufferLength = serializedString.length * 0.75;
1732
1758
  var len = serializedString.length;
@@ -1753,7 +1779,7 @@ function stringToBuffer$1(serializedString) {
1753
1779
  * Converts a buffer to a string to store, serialized, in the backend
1754
1780
  * storage library.
1755
1781
  */
1756
- function bufferToString$1(buffer) {
1782
+ function bufferToString(buffer) {
1757
1783
  // base64-arraybuffer
1758
1784
  var bytes = new Uint8Array(buffer);
1759
1785
  var base64String = '';
@@ -1780,15 +1806,15 @@ function bufferToString$1(buffer) {
1780
1806
  * @param value
1781
1807
  * @param callback
1782
1808
  */
1783
- function serialize$2(value, callback) {
1809
+ function serialize$1(value, callback) {
1784
1810
  var valueType = '';
1785
1811
  if (value) {
1786
- valueType = toString$1.call(value);
1812
+ valueType = toString.call(value);
1787
1813
  }
1788
1814
  // Cannot use `value instanceof ArrayBuffer` or such here, as these
1789
1815
  // checks fail when running the tests using casper.js...
1790
1816
  if (value && (valueType === '[object ArrayBuffer]' ||
1791
- (value.buffer && toString$1.call(value.buffer) === '[object ArrayBuffer]'))) {
1817
+ (value.buffer && toString.call(value.buffer) === '[object ArrayBuffer]'))) {
1792
1818
  // Convert binary arrays to a string and prefix the string with
1793
1819
  // a special marker.
1794
1820
  var buffer = void 0;
@@ -1830,7 +1856,7 @@ function serialize$2(value, callback) {
1830
1856
  callback(new Error('Failed to get type for BinaryArray'));
1831
1857
  }
1832
1858
  }
1833
- callback(marker + bufferToString$1(buffer));
1859
+ callback(marker + bufferToString(buffer));
1834
1860
  }
1835
1861
  else if (valueType === '[object Blob]') {
1836
1862
  // Convert the blob to a binaryArray and then to a string.
@@ -1838,7 +1864,7 @@ function serialize$2(value, callback) {
1838
1864
  fileReader.onload = function () {
1839
1865
  // Backwards-compatible prefix for the blob type.
1840
1866
  //tslint:disable-next-line:restrict-plus-operands
1841
- var str = "~~local_forage_type~" /* BLOB_TYPE_PREFIX */ + value.type + "~" + bufferToString$1(this.result);
1867
+ var str = "~~local_forage_type~" /* BLOB_TYPE_PREFIX */ + value.type + "~" + bufferToString(this.result);
1842
1868
  callback("__lfsc__:" /* SERIALIZED_MARKER */ + "blob" /* TYPE_BLOB */ + str);
1843
1869
  };
1844
1870
  fileReader.readAsArrayBuffer(value);
@@ -1864,34 +1890,34 @@ function serialize$2(value, callback) {
1864
1890
  * some kind of arraybuffer/binary data/typed array out of the string.
1865
1891
  * @param value
1866
1892
  */
1867
- function deserialize$2(value) {
1893
+ function deserialize$1(value) {
1868
1894
  // If we haven't marked this string as being specially serialized (i.e.
1869
1895
  // something other than serialized JSON), we can just return it and be
1870
1896
  // done with it.
1871
- if (value.substring(0, SERIALIZED_MARKER_LENGTH$1) !== "__lfsc__:" /* SERIALIZED_MARKER */) {
1897
+ if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== "__lfsc__:" /* SERIALIZED_MARKER */) {
1872
1898
  return JSON.parse(value);
1873
1899
  }
1874
1900
  // The following code deals with deserializing some kind of Blob or
1875
1901
  // TypedArray. First we separate out the type of data we're dealing
1876
1902
  // with from the data itself.
1877
- var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH$1);
1878
- var type = value.substring(SERIALIZED_MARKER_LENGTH$1, TYPE_SERIALIZED_MARKER_LENGTH$1);
1903
+ var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
1904
+ var type = value.substring(SERIALIZED_MARKER_LENGTH, TYPE_SERIALIZED_MARKER_LENGTH);
1879
1905
  var blobType;
1880
1906
  // Backwards-compatible blob type serialization strategy.
1881
1907
  // DBs created with older versions of localForage will simply not have the blob type.
1882
- if (type === "blob" /* TYPE_BLOB */ && BLOB_TYPE_PREFIX_REGEX$1.test(serializedString)) {
1883
- var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX$1);
1908
+ if (type === "blob" /* TYPE_BLOB */ && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {
1909
+ var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);
1884
1910
  blobType = matcher[1];
1885
1911
  serializedString = serializedString.substring(matcher[0].length);
1886
1912
  }
1887
- var buffer = stringToBuffer$1(serializedString);
1913
+ var buffer = stringToBuffer(serializedString);
1888
1914
  // Return the right type based on the code/type set during
1889
1915
  // serialization.
1890
1916
  switch (type) {
1891
1917
  case "arbf" /* TYPE_ARRAYBUFFER */:
1892
1918
  return buffer;
1893
1919
  case "blob" /* TYPE_BLOB */:
1894
- return createBlob$1([buffer], { type: blobType });
1920
+ return createBlob([buffer], { type: blobType });
1895
1921
  case "si08" /* TYPE_INT8ARRAY */:
1896
1922
  return new Int8Array(buffer);
1897
1923
  case "ui08" /* TYPE_UINT8ARRAY */:
@@ -1945,7 +1971,7 @@ function getKeyPrefix(options, defaultConfig) {
1945
1971
  return (options.name || defaultConfig.name) + "/" + (options.storeName || defaultConfig.storeName) + "/";
1946
1972
  }
1947
1973
 
1948
- function executeCallback$2(promise, callback) {
1974
+ function executeCallback$1(promise, callback) {
1949
1975
  if (callback) {
1950
1976
  promise.then(function (result) {
1951
1977
  callback(null, result);
@@ -1998,10 +2024,10 @@ function normaliseKey(key) {
1998
2024
  }
1999
2025
 
2000
2026
  var serialiser = {
2001
- bufferToString: bufferToString$1,
2002
- deserialize: deserialize$2,
2003
- serialize: serialize$2,
2004
- stringToBuffer: stringToBuffer$1
2027
+ bufferToString: bufferToString,
2028
+ deserialize: deserialize$1,
2029
+ serialize: serialize$1,
2030
+ stringToBuffer: stringToBuffer
2005
2031
  };
2006
2032
 
2007
2033
  /*!
@@ -2086,7 +2112,7 @@ function clear$1(callback) {
2086
2112
  var promise = this.ready().then(function () {
2087
2113
  _this._dbInfo.mStore.clear();
2088
2114
  });
2089
- executeCallback$2(promise, callback);
2115
+ executeCallback$1(promise, callback);
2090
2116
  return promise;
2091
2117
  }
2092
2118
 
@@ -2095,7 +2121,7 @@ function dropInstance$1(_options, _cb) {
2095
2121
  var outPromise = promise.then(function (keyPrefix) {
2096
2122
  Store.resolve(keyPrefix).drop();
2097
2123
  });
2098
- executeCallback$2(outPromise, callback);
2124
+ executeCallback$1(outPromise, callback);
2099
2125
  return promise;
2100
2126
  }
2101
2127
 
@@ -2107,7 +2133,7 @@ function getItem$1(key$, callback) {
2107
2133
  // Deserialise if the result is not null or undefined
2108
2134
  return result == null ? null : _this._dbInfo.serializer.deserialize(result); //tslint:disable-line:triple-equals
2109
2135
  });
2110
- executeCallback$2(promise, callback);
2136
+ executeCallback$1(promise, callback);
2111
2137
  return promise;
2112
2138
  }
2113
2139
 
@@ -2131,7 +2157,7 @@ function iterate$1(iterator, callback) {
2131
2157
  }
2132
2158
  }
2133
2159
  });
2134
- executeCallback$2(promise, callback);
2160
+ executeCallback$1(promise, callback);
2135
2161
  return promise;
2136
2162
  }
2137
2163
 
@@ -2150,7 +2176,7 @@ function key$1(idx, callback) {
2150
2176
  }
2151
2177
  return result;
2152
2178
  });
2153
- executeCallback$2(promise, callback);
2179
+ executeCallback$1(promise, callback);
2154
2180
  return promise;
2155
2181
  }
2156
2182
 
@@ -2159,13 +2185,13 @@ function keys$1(callback) {
2159
2185
  var promise = this.ready().then(function () {
2160
2186
  return _this._dbInfo.mStore.keys();
2161
2187
  });
2162
- executeCallback$2(promise, callback);
2188
+ executeCallback$1(promise, callback);
2163
2189
  return promise;
2164
2190
  }
2165
2191
 
2166
2192
  function length$1(callback) {
2167
2193
  var promise = this.keys().then(function (keys$) { return keys$.length; });
2168
- executeCallback$2(promise, callback);
2194
+ executeCallback$1(promise, callback);
2169
2195
  return promise;
2170
2196
  }
2171
2197
 
@@ -2175,7 +2201,7 @@ function removeItem$1(key$, callback) {
2175
2201
  var promise = this.ready().then(function () {
2176
2202
  _this._dbInfo.mStore.rm(key$);
2177
2203
  });
2178
- executeCallback$2(promise, callback);
2204
+ executeCallback$1(promise, callback);
2179
2205
  return promise;
2180
2206
  }
2181
2207
 
@@ -2205,7 +2231,7 @@ function setItem$1(key$, value, callback) {
2205
2231
  });
2206
2232
  });
2207
2233
  });
2208
- executeCallback$2(promise, callback);
2234
+ executeCallback$1(promise, callback);
2209
2235
  return promise;
2210
2236
  }
2211
2237
 
@@ -2492,10 +2518,10 @@ function hashDelete(key) {
2492
2518
  var HASH_UNDEFINED$2 = '__lodash_hash_undefined__';
2493
2519
 
2494
2520
  /** Used for built-in method references. */
2495
- var objectProto$d = Object.prototype;
2521
+ var objectProto$e = Object.prototype;
2496
2522
 
2497
2523
  /** Used to check objects for own properties. */
2498
- var hasOwnProperty$b = objectProto$d.hasOwnProperty;
2524
+ var hasOwnProperty$c = objectProto$e.hasOwnProperty;
2499
2525
 
2500
2526
  /**
2501
2527
  * Gets the hash value for `key`.
@@ -2512,14 +2538,14 @@ function hashGet(key) {
2512
2538
  var result = data[key];
2513
2539
  return result === HASH_UNDEFINED$2 ? undefined : result;
2514
2540
  }
2515
- return hasOwnProperty$b.call(data, key) ? data[key] : undefined;
2541
+ return hasOwnProperty$c.call(data, key) ? data[key] : undefined;
2516
2542
  }
2517
2543
 
2518
2544
  /** Used for built-in method references. */
2519
- var objectProto$c = Object.prototype;
2545
+ var objectProto$d = Object.prototype;
2520
2546
 
2521
2547
  /** Used to check objects for own properties. */
2522
- var hasOwnProperty$a = objectProto$c.hasOwnProperty;
2548
+ var hasOwnProperty$b = objectProto$d.hasOwnProperty;
2523
2549
 
2524
2550
  /**
2525
2551
  * Checks if a hash value for `key` exists.
@@ -2532,7 +2558,7 @@ var hasOwnProperty$a = objectProto$c.hasOwnProperty;
2532
2558
  */
2533
2559
  function hashHas(key) {
2534
2560
  var data = this.__data__;
2535
- return nativeCreate ? (data[key] !== undefined) : hasOwnProperty$a.call(data, key);
2561
+ return nativeCreate ? (data[key] !== undefined) : hasOwnProperty$b.call(data, key);
2536
2562
  }
2537
2563
 
2538
2564
  /** Used to stand-in for `undefined` hash values. */
@@ -2591,7 +2617,7 @@ function mapCacheClear() {
2591
2617
  this.size = 0;
2592
2618
  this.__data__ = {
2593
2619
  'hash': new Hash,
2594
- 'map': new (Map || ListCache),
2620
+ 'map': new (Map$1 || ListCache),
2595
2621
  'string': new Hash
2596
2622
  };
2597
2623
  }
@@ -2727,7 +2753,7 @@ function stackSet(key, value) {
2727
2753
  var data = this.__data__;
2728
2754
  if (data instanceof ListCache) {
2729
2755
  var pairs = data.__data__;
2730
- if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
2756
+ if (!Map$1 || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
2731
2757
  pairs.push([key, value]);
2732
2758
  this.size = ++data.size;
2733
2759
  return this;
@@ -2810,10 +2836,10 @@ function baseAssignValue(object, key, value) {
2810
2836
  }
2811
2837
 
2812
2838
  /** Used for built-in method references. */
2813
- var objectProto$b = Object.prototype;
2839
+ var objectProto$c = Object.prototype;
2814
2840
 
2815
2841
  /** Used to check objects for own properties. */
2816
- var hasOwnProperty$9 = objectProto$b.hasOwnProperty;
2842
+ var hasOwnProperty$a = objectProto$c.hasOwnProperty;
2817
2843
 
2818
2844
  /**
2819
2845
  * Assigns `value` to `key` of `object` if the existing value is not equivalent
@@ -2827,7 +2853,7 @@ var hasOwnProperty$9 = objectProto$b.hasOwnProperty;
2827
2853
  */
2828
2854
  function assignValue(object, key, value) {
2829
2855
  var objValue = object[key];
2830
- if (!(hasOwnProperty$9.call(object, key) && eq(objValue, value)) ||
2856
+ if (!(hasOwnProperty$a.call(object, key) && eq(objValue, value)) ||
2831
2857
  (value === undefined && !(key in object))) {
2832
2858
  baseAssignValue(object, key, value);
2833
2859
  }
@@ -2900,10 +2926,10 @@ function nativeKeysIn(object) {
2900
2926
  }
2901
2927
 
2902
2928
  /** Used for built-in method references. */
2903
- var objectProto$a = Object.prototype;
2929
+ var objectProto$b = Object.prototype;
2904
2930
 
2905
2931
  /** Used to check objects for own properties. */
2906
- var hasOwnProperty$8 = objectProto$a.hasOwnProperty;
2932
+ var hasOwnProperty$9 = objectProto$b.hasOwnProperty;
2907
2933
 
2908
2934
  /**
2909
2935
  * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
@@ -2920,7 +2946,7 @@ function baseKeysIn(object) {
2920
2946
  result = [];
2921
2947
 
2922
2948
  for (var key in object) {
2923
- if (!(key == 'constructor' && (isProto || !hasOwnProperty$8.call(object, key)))) {
2949
+ if (!(key == 'constructor' && (isProto || !hasOwnProperty$9.call(object, key)))) {
2924
2950
  result.push(key);
2925
2951
  }
2926
2952
  }
@@ -3065,10 +3091,10 @@ function stubArray() {
3065
3091
  }
3066
3092
 
3067
3093
  /** Used for built-in method references. */
3068
- var objectProto$9 = Object.prototype;
3094
+ var objectProto$a = Object.prototype;
3069
3095
 
3070
3096
  /** Built-in value references. */
3071
- var propertyIsEnumerable = objectProto$9.propertyIsEnumerable;
3097
+ var propertyIsEnumerable = objectProto$a.propertyIsEnumerable;
3072
3098
 
3073
3099
  /* Built-in method references for those with the same name as other `lodash` methods. */
3074
3100
  var nativeGetSymbols$1 = Object.getOwnPropertySymbols;
@@ -3195,10 +3221,10 @@ function getAllKeysIn(object) {
3195
3221
  }
3196
3222
 
3197
3223
  /** Used for built-in method references. */
3198
- var objectProto$8 = Object.prototype;
3224
+ var objectProto$9 = Object.prototype;
3199
3225
 
3200
3226
  /** Used to check objects for own properties. */
3201
- var hasOwnProperty$7 = objectProto$8.hasOwnProperty;
3227
+ var hasOwnProperty$8 = objectProto$9.hasOwnProperty;
3202
3228
 
3203
3229
  /**
3204
3230
  * Initializes an array clone.
@@ -3212,7 +3238,7 @@ function initCloneArray(array) {
3212
3238
  result = new array.constructor(length);
3213
3239
 
3214
3240
  // Add properties assigned by `RegExp#exec`.
3215
- if (length && typeof array[0] == 'string' && hasOwnProperty$7.call(array, 'index')) {
3241
+ if (length && typeof array[0] == 'string' && hasOwnProperty$8.call(array, 'index')) {
3216
3242
  result.index = array.index;
3217
3243
  result.input = array.input;
3218
3244
  }
@@ -6592,13 +6618,13 @@ var objectTag$1 = '[object Object]';
6592
6618
 
6593
6619
  /** Used for built-in method references. */
6594
6620
  var funcProto = Function.prototype,
6595
- objectProto$7 = Object.prototype;
6621
+ objectProto$8 = Object.prototype;
6596
6622
 
6597
6623
  /** Used to resolve the decompiled source of functions. */
6598
6624
  var funcToString = funcProto.toString;
6599
6625
 
6600
6626
  /** Used to check objects for own properties. */
6601
- var hasOwnProperty$6 = objectProto$7.hasOwnProperty;
6627
+ var hasOwnProperty$7 = objectProto$8.hasOwnProperty;
6602
6628
 
6603
6629
  /** Used to infer the `Object` constructor. */
6604
6630
  var objectCtorString = funcToString.call(Object);
@@ -6639,7 +6665,7 @@ function isPlainObject(value) {
6639
6665
  if (proto === null) {
6640
6666
  return true;
6641
6667
  }
6642
- var Ctor = hasOwnProperty$6.call(proto, 'constructor') && proto.constructor;
6668
+ var Ctor = hasOwnProperty$7.call(proto, 'constructor') && proto.constructor;
6643
6669
  return typeof Ctor == 'function' && Ctor instanceof Ctor &&
6644
6670
  funcToString.call(Ctor) == objectCtorString;
6645
6671
  }
@@ -7371,310 +7397,43 @@ function mergebounce(func, wait, options={}) {
7371
7397
  return debounced;
7372
7398
  }
7373
7399
 
7374
- function executeCallback$1(promise, callback) {
7400
+ function chainCallback(promise, callback) {
7375
7401
  if (callback) {
7376
- promise.then(
7377
- function(result) {
7378
- callback(null, result);
7379
- },
7380
- function(error) {
7381
- callback(error);
7382
- }
7383
- );
7402
+ promise.then((result) => callback(null, result), (err) => callback(err));
7384
7403
  }
7385
7404
  }
7386
-
7387
- function getCallback() {
7388
- if (
7389
- arguments.length &&
7390
- typeof arguments[arguments.length - 1] === 'function'
7391
- ) {
7392
- return arguments[arguments.length - 1];
7405
+ function getCallback(...args) {
7406
+ if (args.length && typeof args[args.length - 1] === 'function') {
7407
+ return args[args.length - 1];
7393
7408
  }
7394
7409
  }
7395
-
7396
7410
  function normalizeKey(key) {
7397
- // Cast the key to a string, as that's all we can set as a key.
7398
7411
  if (typeof key !== 'string') {
7399
7412
  console.warn(`${key} used as a key, but it is not a string.`);
7400
7413
  key = String(key);
7401
7414
  }
7402
-
7403
7415
  return key;
7404
7416
  }
7405
-
7406
- // Abstracts constructing a Blob object, so it also works in older
7407
- // browsers that don't support the native Blob constructor. (i.e.
7408
- // old QtWebKit versions, at least).
7409
- // Abstracts constructing a Blob object, so it also works in older
7410
- // browsers that don't support the native Blob constructor. (i.e.
7411
- // old QtWebKit versions, at least).
7412
- function createBlob(parts, properties) {
7413
- /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */
7414
- parts = parts || [];
7415
- properties = properties || {};
7416
- try {
7417
- return new Blob(parts, properties);
7418
- } catch (e) {
7419
- if (e.name !== 'TypeError') {
7420
- throw e;
7421
- }
7422
- var Builder =
7423
- typeof BlobBuilder !== 'undefined'
7424
- ? BlobBuilder
7425
- : typeof MSBlobBuilder !== 'undefined'
7426
- ? MSBlobBuilder
7427
- : typeof MozBlobBuilder !== 'undefined'
7428
- ? MozBlobBuilder
7429
- : WebKitBlobBuilder;
7430
- var builder = new Builder();
7431
- for (var i = 0; i < parts.length; i += 1) {
7432
- builder.append(parts[i]);
7417
+ function serializeSync(value) {
7418
+ return JSON.stringify(value, (_key, val) => {
7419
+ if (val instanceof Date) {
7420
+ return val.toISOString();
7433
7421
  }
7434
- return builder.getBlob(properties.type);
7435
- }
7436
- }
7437
-
7438
- /* eslint-disable no-bitwise */
7439
-
7440
- // Sadly, the best way to save binary data in WebSQL/localStorage is serializing
7441
- // it to Base64, so this is how we store it to prevent very strange errors with less
7442
- // verbose ways of binary <-> string data storage.
7443
- var BASE_CHARS =
7444
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
7445
-
7446
- var BLOB_TYPE_PREFIX = '~~local_forage_type~';
7447
- var BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;
7448
-
7449
- var SERIALIZED_MARKER = '__lfsc__:';
7450
- var SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length;
7451
-
7452
- // OMG the serializations!
7453
- var TYPE_ARRAYBUFFER = 'arbf';
7454
- var TYPE_BLOB = 'blob';
7455
- var TYPE_INT8ARRAY = 'si08';
7456
- var TYPE_UINT8ARRAY = 'ui08';
7457
- var TYPE_UINT8CLAMPEDARRAY = 'uic8';
7458
- var TYPE_INT16ARRAY = 'si16';
7459
- var TYPE_INT32ARRAY = 'si32';
7460
- var TYPE_UINT16ARRAY = 'ur16';
7461
- var TYPE_UINT32ARRAY = 'ui32';
7462
- var TYPE_FLOAT32ARRAY = 'fl32';
7463
- var TYPE_FLOAT64ARRAY = 'fl64';
7464
- var TYPE_SERIALIZED_MARKER_LENGTH =
7465
- SERIALIZED_MARKER_LENGTH + TYPE_ARRAYBUFFER.length;
7466
-
7467
- var toString = Object.prototype.toString;
7468
-
7469
- function stringToBuffer(serializedString) {
7470
- // Fill the string into a ArrayBuffer.
7471
- var bufferLength = serializedString.length * 0.75;
7472
- var len = serializedString.length;
7473
- var i;
7474
- var p = 0;
7475
- var encoded1, encoded2, encoded3, encoded4;
7476
-
7477
- if (serializedString[serializedString.length - 1] === '=') {
7478
- bufferLength--;
7479
- if (serializedString[serializedString.length - 2] === '=') {
7480
- bufferLength--;
7481
- }
7482
- }
7483
-
7484
- var buffer = new ArrayBuffer(bufferLength);
7485
- var bytes = new Uint8Array(buffer);
7486
-
7487
- for (i = 0; i < len; i += 4) {
7488
- encoded1 = BASE_CHARS.indexOf(serializedString[i]);
7489
- encoded2 = BASE_CHARS.indexOf(serializedString[i + 1]);
7490
- encoded3 = BASE_CHARS.indexOf(serializedString[i + 2]);
7491
- encoded4 = BASE_CHARS.indexOf(serializedString[i + 3]);
7492
-
7493
- /*jslint bitwise: true */
7494
- bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
7495
- bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
7496
- bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
7497
- }
7498
- return buffer;
7422
+ return val;
7423
+ });
7499
7424
  }
7500
-
7501
- // Converts a buffer to a string to store, serialized, in the backend
7502
- // storage library.
7503
- function bufferToString(buffer) {
7504
- // base64-arraybuffer
7505
- var bytes = new Uint8Array(buffer);
7506
- var base64String = '';
7507
- var i;
7508
-
7509
- for (i = 0; i < bytes.length; i += 3) {
7510
- /*jslint bitwise: true */
7511
- base64String += BASE_CHARS[bytes[i] >> 2];
7512
- base64String += BASE_CHARS[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
7513
- base64String +=
7514
- BASE_CHARS[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
7515
- base64String += BASE_CHARS[bytes[i + 2] & 63];
7425
+ function serialize(value, callback) {
7426
+ try {
7427
+ callback(serializeSync(value), null);
7516
7428
  }
7517
-
7518
- if (bytes.length % 3 === 2) {
7519
- base64String = base64String.substring(0, base64String.length - 1) + '=';
7520
- } else if (bytes.length % 3 === 1) {
7521
- base64String =
7522
- base64String.substring(0, base64String.length - 2) + '==';
7429
+ catch (e) {
7430
+ callback('', e);
7523
7431
  }
7524
-
7525
- return base64String;
7526
7432
  }
7527
-
7528
- // Serialize a value, afterwards executing a callback (which usually
7529
- // instructs the `setItem()` callback/promise to be executed). This is how
7530
- // we store binary data with localStorage.
7531
- function serialize$1(value, callback) {
7532
- var valueType = '';
7533
- if (value) {
7534
- valueType = toString.call(value);
7535
- }
7536
-
7537
- // Cannot use `value instanceof ArrayBuffer` or such here, as these
7538
- // checks fail when running the tests using casper.js...
7539
- //
7540
- // TODO: See why those tests fail and use a better solution.
7541
- if (
7542
- value &&
7543
- (valueType === '[object ArrayBuffer]' ||
7544
- (value.buffer &&
7545
- toString.call(value.buffer) === '[object ArrayBuffer]'))
7546
- ) {
7547
- // Convert binary arrays to a string and prefix the string with
7548
- // a special marker.
7549
- var buffer;
7550
- var marker = SERIALIZED_MARKER;
7551
-
7552
- if (value instanceof ArrayBuffer) {
7553
- buffer = value;
7554
- marker += TYPE_ARRAYBUFFER;
7555
- } else {
7556
- buffer = value.buffer;
7557
-
7558
- if (valueType === '[object Int8Array]') {
7559
- marker += TYPE_INT8ARRAY;
7560
- } else if (valueType === '[object Uint8Array]') {
7561
- marker += TYPE_UINT8ARRAY;
7562
- } else if (valueType === '[object Uint8ClampedArray]') {
7563
- marker += TYPE_UINT8CLAMPEDARRAY;
7564
- } else if (valueType === '[object Int16Array]') {
7565
- marker += TYPE_INT16ARRAY;
7566
- } else if (valueType === '[object Uint16Array]') {
7567
- marker += TYPE_UINT16ARRAY;
7568
- } else if (valueType === '[object Int32Array]') {
7569
- marker += TYPE_INT32ARRAY;
7570
- } else if (valueType === '[object Uint32Array]') {
7571
- marker += TYPE_UINT32ARRAY;
7572
- } else if (valueType === '[object Float32Array]') {
7573
- marker += TYPE_FLOAT32ARRAY;
7574
- } else if (valueType === '[object Float64Array]') {
7575
- marker += TYPE_FLOAT64ARRAY;
7576
- } else {
7577
- callback(new Error('Failed to get type for BinaryArray'));
7578
- }
7579
- }
7580
-
7581
- callback(marker + bufferToString(buffer));
7582
- } else if (valueType === '[object Blob]') {
7583
- // Conver the blob to a binaryArray and then to a string.
7584
- var fileReader = new FileReader();
7585
-
7586
- fileReader.onload = function() {
7587
- // Backwards-compatible prefix for the blob type.
7588
- var str =
7589
- BLOB_TYPE_PREFIX +
7590
- value.type +
7591
- '~' +
7592
- bufferToString(this.result);
7593
-
7594
- callback(SERIALIZED_MARKER + TYPE_BLOB + str);
7595
- };
7596
-
7597
- fileReader.readAsArrayBuffer(value);
7598
- } else {
7599
- try {
7600
- callback(JSON.stringify(value));
7601
- } catch (e) {
7602
- console.error("Couldn't convert value into a JSON string: ", value);
7603
-
7604
- callback(null, e);
7605
- }
7606
- }
7433
+ function deserialize(value) {
7434
+ return JSON.parse(value);
7607
7435
  }
7608
7436
 
7609
- // Deserialize data we've inserted into a value column/field. We place
7610
- // special markers into our strings to mark them as encoded; this isn't
7611
- // as nice as a meta field, but it's the only sane thing we can do whilst
7612
- // keeping localStorage support intact.
7613
- //
7614
- // Oftentimes this will just deserialize JSON content, but if we have a
7615
- // special marker (SERIALIZED_MARKER, defined above), we will extract
7616
- // some kind of arraybuffer/binary data/typed array out of the string.
7617
- function deserialize$1(value) {
7618
- // If we haven't marked this string as being specially serialized (i.e.
7619
- // something other than serialized JSON), we can just return it and be
7620
- // done with it.
7621
- if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {
7622
- return JSON.parse(value);
7623
- }
7624
-
7625
- // The following code deals with deserializing some kind of Blob or
7626
- // TypedArray. First we separate out the type of data we're dealing
7627
- // with from the data itself.
7628
- var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
7629
- var type = value.substring(
7630
- SERIALIZED_MARKER_LENGTH,
7631
- TYPE_SERIALIZED_MARKER_LENGTH
7632
- );
7633
-
7634
- var blobType;
7635
- // Backwards-compatible blob type serialization strategy.
7636
- // DBs created with older versions of localForage will simply not have the blob type.
7637
- if (type === TYPE_BLOB && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {
7638
- var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);
7639
- blobType = matcher[1];
7640
- serializedString = serializedString.substring(matcher[0].length);
7641
- }
7642
- var buffer = stringToBuffer(serializedString);
7643
-
7644
- // Return the right type based on the code/type set during
7645
- // serialization.
7646
- switch (type) {
7647
- case TYPE_ARRAYBUFFER:
7648
- return buffer;
7649
- case TYPE_BLOB:
7650
- return createBlob([buffer], { type: blobType });
7651
- case TYPE_INT8ARRAY:
7652
- return new Int8Array(buffer);
7653
- case TYPE_UINT8ARRAY:
7654
- return new Uint8Array(buffer);
7655
- case TYPE_UINT8CLAMPEDARRAY:
7656
- return new Uint8ClampedArray(buffer);
7657
- case TYPE_INT16ARRAY:
7658
- return new Int16Array(buffer);
7659
- case TYPE_UINT16ARRAY:
7660
- return new Uint16Array(buffer);
7661
- case TYPE_INT32ARRAY:
7662
- return new Int32Array(buffer);
7663
- case TYPE_UINT32ARRAY:
7664
- return new Uint32Array(buffer);
7665
- case TYPE_FLOAT32ARRAY:
7666
- return new Float32Array(buffer);
7667
- case TYPE_FLOAT64ARRAY:
7668
- return new Float64Array(buffer);
7669
- default:
7670
- throw new Error('Unkown type: ' + type);
7671
- }
7672
- }
7673
-
7674
- var localforageSerializer = {
7675
- serialize: serialize$1,
7676
- deserialize: deserialize$1};
7677
-
7678
7437
  // Copyright 2014 Mozilla
7679
7438
  // Copyright 2015 Thodoris Greasidis
7680
7439
  // Copyright 2018-2025 JC Brand
@@ -7690,8 +7449,6 @@ var localforageSerializer = {
7690
7449
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7691
7450
  // See the License for the specific language governing permissions and
7692
7451
  // limitations under the License.
7693
- const serialize = localforageSerializer['serialize'];
7694
- const deserialize = localforageSerializer['deserialize'];
7695
7452
  function isSessionStorageValid() {
7696
7453
  try {
7697
7454
  if (sessionStorage && 'setItem' in sessionStorage) {
@@ -7737,7 +7494,7 @@ function clear(callback) {
7737
7494
  }
7738
7495
  }
7739
7496
  });
7740
- executeCallback$1(promise, callback);
7497
+ chainCallback(promise, callback);
7741
7498
  return promise;
7742
7499
  }
7743
7500
  function getItem(key, callback) {
@@ -7753,7 +7510,7 @@ function getItem(key, callback) {
7753
7510
  }
7754
7511
  return null;
7755
7512
  });
7756
- executeCallback$1(promise, callback);
7513
+ chainCallback(promise, callback);
7757
7514
  return promise;
7758
7515
  }
7759
7516
  function iterate(iterator, callback) {
@@ -7781,7 +7538,7 @@ function iterate(iterator, callback) {
7781
7538
  }
7782
7539
  return;
7783
7540
  });
7784
- executeCallback$1(promise, callback);
7541
+ chainCallback(promise, callback);
7785
7542
  return promise;
7786
7543
  }
7787
7544
  // Same as sessionStorage's key() method, except takes a callback.
@@ -7801,7 +7558,7 @@ function key(n, callback) {
7801
7558
  }
7802
7559
  return result;
7803
7560
  });
7804
- executeCallback$1(promise, callback);
7561
+ chainCallback(promise, callback);
7805
7562
  return promise;
7806
7563
  }
7807
7564
  function keys(callback) {
@@ -7817,7 +7574,7 @@ function keys(callback) {
7817
7574
  }
7818
7575
  return keys;
7819
7576
  });
7820
- executeCallback$1(promise, callback);
7577
+ chainCallback(promise, callback);
7821
7578
  return promise;
7822
7579
  }
7823
7580
  // Supply the number of keys in the datastore to the callback function.
@@ -7826,7 +7583,7 @@ function length(callback) {
7826
7583
  const promise = self.keys().then(function (keys) {
7827
7584
  return keys.length;
7828
7585
  });
7829
- executeCallback$1(promise, callback);
7586
+ chainCallback(promise, callback);
7830
7587
  return promise;
7831
7588
  }
7832
7589
  function removeItem(key, callback) {
@@ -7834,7 +7591,7 @@ function removeItem(key, callback) {
7834
7591
  const promise = this.ready().then(function () {
7835
7592
  sessionStorage.removeItem(dbInfo.keyPrefix + key);
7836
7593
  });
7837
- executeCallback$1(promise, callback);
7594
+ chainCallback(promise, callback);
7838
7595
  return promise;
7839
7596
  }
7840
7597
  async function setItem(key, value, callback) {
@@ -7846,27 +7603,27 @@ async function setItem(key, value, callback) {
7846
7603
  dbInfo.serializer.serialize(value, (serializedValue, error) => {
7847
7604
  if (error) {
7848
7605
  reject(error);
7849
- executeCallback$1(Promise.reject(error), callback);
7606
+ chainCallback(Promise.reject(error), callback);
7850
7607
  return;
7851
7608
  }
7852
7609
  try {
7853
7610
  sessionStorage.setItem(dbInfo.keyPrefix + key, serializedValue);
7854
7611
  resolve(originalValue);
7855
- executeCallback$1(Promise.resolve(originalValue), callback);
7612
+ chainCallback(Promise.resolve(originalValue), callback);
7856
7613
  }
7857
7614
  catch (e) {
7858
7615
  if (e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
7859
7616
  console.error('Your sessionStorage capacity is used up.');
7860
7617
  }
7861
7618
  reject(e);
7862
- executeCallback$1(Promise.reject(e), callback);
7619
+ chainCallback(Promise.reject(e), callback);
7863
7620
  }
7864
7621
  });
7865
7622
  });
7866
7623
  }
7867
- function dropInstance(options, callback) {
7868
- callback = getCallback.apply(this, arguments);
7869
- options = (typeof options !== 'function' && options) || {};
7624
+ function dropInstance(...args) {
7625
+ const callback = getCallback(...args);
7626
+ let options = (typeof args[0] !== 'function' && args[0]) || {};
7870
7627
  if (!options.name) {
7871
7628
  const currentConfig = this.config();
7872
7629
  options.name = options.name || currentConfig.name;
@@ -7894,7 +7651,7 @@ function dropInstance(options, callback) {
7894
7651
  }
7895
7652
  });
7896
7653
  }
7897
- executeCallback$1(promise, callback);
7654
+ chainCallback(promise, callback);
7898
7655
  return promise;
7899
7656
  }
7900
7657
  const sessionStorageWrapper = {
@@ -8373,10 +8130,10 @@ function extendPrototype(localforage$$1) {
8373
8130
  extendPrototype(localForage);
8374
8131
 
8375
8132
  /** Used for built-in method references. */
8376
- var objectProto$6 = Object.prototype;
8133
+ var objectProto$7 = Object.prototype;
8377
8134
 
8378
8135
  /** Used to check objects for own properties. */
8379
- var hasOwnProperty$5 = objectProto$6.hasOwnProperty;
8136
+ var hasOwnProperty$6 = objectProto$7.hasOwnProperty;
8380
8137
 
8381
8138
  /**
8382
8139
  * The base implementation of `_.has` without support for deep paths.
@@ -8387,7 +8144,7 @@ var hasOwnProperty$5 = objectProto$6.hasOwnProperty;
8387
8144
  * @returns {boolean} Returns `true` if `key` exists, else `false`.
8388
8145
  */
8389
8146
  function baseHas(object, key) {
8390
- return object != null && hasOwnProperty$5.call(object, key);
8147
+ return object != null && hasOwnProperty$6.call(object, key);
8391
8148
  }
8392
8149
 
8393
8150
  /** Used to match property names within property paths. */
@@ -8544,7 +8301,7 @@ function castPath(value, object) {
8544
8301
  if (isArray(value)) {
8545
8302
  return value;
8546
8303
  }
8547
- return isKey(value, object) ? [value] : stringToPath(toString$2(value));
8304
+ return isKey(value, object) ? [value] : stringToPath(toString$1(value));
8548
8305
  }
8549
8306
 
8550
8307
  /**
@@ -8698,16 +8455,18 @@ function getResolveablePromise() {
8698
8455
  wrapper.reject = reject;
8699
8456
  });
8700
8457
  Object.assign(promise, wrapper);
8701
- promise.then(function (v) {
8458
+ // This `then` only mirrors settlement into the state flags. It must NOT
8459
+ // rethrow on rejection: the derived promise is discarded, so rethrowing would
8460
+ // surface as an unhandled rejection whenever the promise is rejected. The real
8461
+ // consumer still awaits `promise` itself, which rejects normally.
8462
+ promise.then(function () {
8702
8463
  promise.isResolved = true;
8703
8464
  promise.isPending = false;
8704
8465
  promise.isRejected = false;
8705
- return v;
8706
- }, function (e) {
8466
+ }, function () {
8707
8467
  promise.isResolved = false;
8708
8468
  promise.isPending = false;
8709
8469
  promise.isRejected = true;
8710
- throw e;
8711
8470
  });
8712
8471
  return promise;
8713
8472
  }
@@ -8715,13 +8474,16 @@ function getResolveablePromise() {
8715
8474
  function urlError() {
8716
8475
  throw new Error('A "url" property or function must be specified');
8717
8476
  }
8718
- // Wrap an optional error callback with a fallback error event.
8719
- function wrapError(model, options) {
8477
+ // Wrap an optional error callback with a fallback error event. When a
8478
+ // `promise` is supplied (the `{ promise: true }` fetch/save path), the error is
8479
+ // also forwarded to `promise.reject` so the returned promise settles on failure.
8480
+ function wrapError(model, options, promise) {
8720
8481
  const error = options.error;
8721
8482
  options.error = function (resp) {
8722
8483
  if (error)
8723
8484
  error.call(options.context, model, resp, options);
8724
8485
  model.trigger('error', model, resp, options);
8486
+ promise && promise.reject && promise.reject(resp);
8725
8487
  };
8726
8488
  }
8727
8489
  // Map from CRUD to HTTP for our default `sync` implementation.
@@ -8732,8 +8494,44 @@ const methodMap = {
8732
8494
  delete: 'DELETE',
8733
8495
  read: 'GET',
8734
8496
  };
8497
+ // Tracks the classes we've already warned about, so the `browserStorage`
8498
+ // deprecation notice is logged at most once per class rather than once per
8499
+ // instance (a collection can resolve storage once per contained model).
8500
+ const warnedBrowserStorage = new WeakSet();
8501
+ /**
8502
+ * Emit a one-time-per-class deprecation warning nudging downstream code from
8503
+ * the `browserStorage` alias to the canonical `storage` accessor.
8504
+ */
8505
+ function warnBrowserStorageDeprecation(obj) {
8506
+ const ctor = obj?.constructor;
8507
+ if (!ctor || warnedBrowserStorage.has(ctor))
8508
+ return;
8509
+ warnedBrowserStorage.add(ctor);
8510
+ const name = ctor.name;
8511
+ console.warn(`Skeletor: \`browserStorage\` is deprecated and will be removed in a future major version; ` +
8512
+ `use \`storage\` instead${name ? ` (on \`${name}\`)` : ''}.`);
8513
+ }
8514
+ /**
8515
+ * Return the PersistentStorage instance configured on `obj`, checking both
8516
+ * the canonical `storage` accessor and the deprecated `browserStorage` alias
8517
+ * so that subclasses that still override `get browserStorage()` continue to work.
8518
+ * @public
8519
+ */
8520
+ function getStorage(obj) {
8521
+ if (!obj)
8522
+ return undefined;
8523
+ const storage = result(obj, 'storage');
8524
+ if (storage != null)
8525
+ return storage;
8526
+ // Fall back to the deprecated alias; warn only when it actually supplies the
8527
+ // store, so storage-less models/collections don't trip the notice.
8528
+ const legacy = result(obj, 'browserStorage');
8529
+ if (legacy != null)
8530
+ warnBrowserStorageDeprecation(obj);
8531
+ return legacy;
8532
+ }
8735
8533
  function getSyncMethod(model) {
8736
- const store = result(model, 'browserStorage') || result(model.collection, 'browserStorage');
8534
+ const store = getStorage(model) || getStorage(model.collection);
8737
8535
  return store ? store.sync() : sync;
8738
8536
  }
8739
8537
  /**
@@ -8783,15 +8581,56 @@ const IN_MEMORY = _driver;
8783
8581
  localForage.defineDriver(memoryDriver);
8784
8582
  localforageSetitemsExports.extendPrototype(localForage);
8785
8583
  extendPrototype(localForage);
8584
+ // Every storage instance is registered with a WeakRef so that flushAll() can
8585
+ // reach pending writes without keeping instances alive. There's no leak and no
8586
+ // lifecycle hook to maintain: an instance is collected once its owning model or
8587
+ // collection is gone, at which point nothing is writing through it anyway.
8588
+ // Models with a pending debounced save stay reachable via the autosync `pending`
8589
+ // map until the timer fires, so flushAll() always reaches in-flight writes.
8590
+ const weakInstances = new Set();
8591
+ // Tracks which instances already have a WeakRef in `weakInstances`, so repeated
8592
+ // `storage =` assignments (or a store shared across models) don't register the
8593
+ // same instance twice and make flushAll() flush it more than once.
8594
+ const registered = new WeakSet();
8786
8595
  /**
8787
8596
  * @public
8788
8597
  */
8789
- class BrowserStorage {
8598
+ class PersistentStorage {
8599
+ /** Register a storage instance with a weak reference. @public */
8600
+ static register(instance) {
8601
+ if (registered.has(instance))
8602
+ return;
8603
+ registered.add(instance);
8604
+ weakInstances.add(new WeakRef(instance));
8605
+ }
8606
+ /**
8607
+ * Flush the debounced write buffer of every registered PersistentStorage
8608
+ * instance. Called automatically on pagehide/visibilitychange when autoSync
8609
+ * is in use; can also be called manually.
8610
+ * @public
8611
+ */
8612
+ static flushAll() {
8613
+ for (const ref of weakInstances) {
8614
+ const instance = ref.deref();
8615
+ if (!instance) {
8616
+ weakInstances.delete(ref);
8617
+ }
8618
+ else {
8619
+ instance.flush();
8620
+ }
8621
+ }
8622
+ }
8790
8623
  constructor(id, type, batchedWrites = false) {
8791
- if (type === 'local' && !window.localStorage) {
8624
+ // Set once `storeInitialized` resolves. Lets `sync()` skip awaiting it on the
8625
+ // hot path so a save buffers/issues its write *synchronously*, which is what
8626
+ // makes the synchronous unload flush (`flushPending` -> `flushAll`) able to
8627
+ // push a pending write out before the page is torn down.
8628
+ this.storeReady = false;
8629
+ this.name = id;
8630
+ if (type === 'local' && typeof window !== 'undefined' && !window.localStorage) {
8792
8631
  throw new Error('Skeletor.storage: Environment does not support localStorage.');
8793
8632
  }
8794
- else if (type === 'session' && !window.sessionStorage) {
8633
+ else if (type === 'session' && typeof window !== 'undefined' && !window.sessionStorage) {
8795
8634
  throw new Error('Skeletor.storage: Environment does not support sessionStorage.');
8796
8635
  }
8797
8636
  if (isString(type)) {
@@ -8806,10 +8645,13 @@ class BrowserStorage {
8806
8645
  }
8807
8646
  this.storeInitialized = Promise.resolve();
8808
8647
  }
8809
- this.name = id;
8648
+ // Flip the synchronous-readiness flag once init settles. Callers that await
8649
+ // `storeInitialized` directly still see any rejection; this branch only
8650
+ // exists to set the flag and must not raise an unhandled rejection.
8651
+ this.storeInitialized.then(() => (this.storeReady = true)).catch(() => { });
8810
8652
  }
8811
8653
  /**
8812
- * @param type - The storage type: 'local', 'session', 'indexed', or 'in_memory'
8654
+ * @param type - The storage type: 'local', 'session', 'indexed', 'node', or 'in_memory'
8813
8655
  * @param batchedWrites - Whether to enable batched writes
8814
8656
  */
8815
8657
  async initStore(type, batchedWrites) {
@@ -8822,6 +8664,16 @@ class BrowserStorage {
8822
8664
  else if (type === 'in_memory') {
8823
8665
  await localForage.config({ 'driver': IN_MEMORY });
8824
8666
  }
8667
+ else if (type === 'node') {
8668
+ const { NodeSQLiteStorage } = await import('./drivers/nodeSQLiteStorage');
8669
+ this.store = new NodeSQLiteStorage(this.name);
8670
+ if (batchedWrites) {
8671
+ this.store.debouncedSetItems = mergebounce((items) => this.store.setItems(items), 50, {
8672
+ 'promise': true,
8673
+ });
8674
+ }
8675
+ return;
8676
+ }
8825
8677
  else if (type !== 'indexed') {
8826
8678
  throw new Error('Skeletor.storage: No storage type was specified');
8827
8679
  }
@@ -8838,6 +8690,7 @@ class BrowserStorage {
8838
8690
  }
8839
8691
  }
8840
8692
  async clear() {
8693
+ await this.storeInitialized;
8841
8694
  await this.store.removeItem(this.name).catch((e) => console.error(e));
8842
8695
  const re = new RegExp(`^${this.name}-`);
8843
8696
  const keys = await this.store.keys();
@@ -8852,12 +8705,16 @@ class BrowserStorage {
8852
8705
  // We get the collection (and if necessary the model attribute.
8853
8706
  // Waiting for storeInitialized will cause another iteration of
8854
8707
  // the event loop, after which the collection reference will
8855
- // be removed from the model.
8856
- const collection = model.collection;
8708
+ // be removed from the model. `options.collection` lets a deferred
8709
+ // delete (sequenced behind an in-flight auto-save by Model.destroy)
8710
+ // supply the collection captured before its optimistic removal.
8711
+ const collection = options.collection ?? model.collection;
8857
8712
  if (['patch', 'update'].includes(method)) {
8858
8713
  new_attributes = cloneDeep(model.attributes);
8859
8714
  }
8860
- await that.storeInitialized;
8715
+ // Skip `await` if not necessary to allow for sync flushing
8716
+ if (!that.storeReady)
8717
+ await that.storeInitialized;
8861
8718
  try {
8862
8719
  const original_attributes = model.attributes;
8863
8720
  switch (method) {
@@ -9012,8 +8869,8 @@ class BrowserStorage {
9012
8869
  return this.name + '-' + id;
9013
8870
  }
9014
8871
  }
9015
- BrowserStorage.sessionStorageInitialized = localForage.defineDriver(sessionStorageWrapper);
9016
- BrowserStorage.localForage = localForage;
8872
+ PersistentStorage.sessionStorageInitialized = localForage.defineDriver(sessionStorageWrapper);
8873
+ PersistentStorage.localForage = localForage;
9017
8874
 
9018
8875
  /** Used to compose bitmasks for cloning. */
9019
8876
  var CLONE_SYMBOLS_FLAG$1 = 4;
@@ -9163,7 +9020,7 @@ function setCacheAdd(value) {
9163
9020
  * @name has
9164
9021
  * @memberOf SetCache
9165
9022
  * @param {*} value The value to search for.
9166
- * @returns {number} Returns `true` if `value` is found, else `false`.
9023
+ * @returns {boolean} Returns `true` if `value` is found, else `false`.
9167
9024
  */
9168
9025
  function setCacheHas(value) {
9169
9026
  return this.__data__.has(value);
@@ -9446,10 +9303,10 @@ function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
9446
9303
  var COMPARE_PARTIAL_FLAG$3 = 1;
9447
9304
 
9448
9305
  /** Used for built-in method references. */
9449
- var objectProto$5 = Object.prototype;
9306
+ var objectProto$6 = Object.prototype;
9450
9307
 
9451
9308
  /** Used to check objects for own properties. */
9452
- var hasOwnProperty$4 = objectProto$5.hasOwnProperty;
9309
+ var hasOwnProperty$5 = objectProto$6.hasOwnProperty;
9453
9310
 
9454
9311
  /**
9455
9312
  * A specialized version of `baseIsEqualDeep` for objects with support for
@@ -9477,7 +9334,7 @@ function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
9477
9334
  var index = objLength;
9478
9335
  while (index--) {
9479
9336
  var key = objProps[index];
9480
- if (!(isPartial ? key in other : hasOwnProperty$4.call(other, key))) {
9337
+ if (!(isPartial ? key in other : hasOwnProperty$5.call(other, key))) {
9481
9338
  return false;
9482
9339
  }
9483
9340
  }
@@ -9538,10 +9395,10 @@ var argsTag = '[object Arguments]',
9538
9395
  objectTag = '[object Object]';
9539
9396
 
9540
9397
  /** Used for built-in method references. */
9541
- var objectProto$4 = Object.prototype;
9398
+ var objectProto$5 = Object.prototype;
9542
9399
 
9543
9400
  /** Used to check objects for own properties. */
9544
- var hasOwnProperty$3 = objectProto$4.hasOwnProperty;
9401
+ var hasOwnProperty$4 = objectProto$5.hasOwnProperty;
9545
9402
 
9546
9403
  /**
9547
9404
  * A specialized version of `baseIsEqual` for arrays and objects which performs
@@ -9584,8 +9441,8 @@ function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
9584
9441
  : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
9585
9442
  }
9586
9443
  if (!(bitmask & COMPARE_PARTIAL_FLAG$2)) {
9587
- var objIsWrapped = objIsObj && hasOwnProperty$3.call(object, '__wrapped__'),
9588
- othIsWrapped = othIsObj && hasOwnProperty$3.call(other, '__wrapped__');
9444
+ var objIsWrapped = objIsObj && hasOwnProperty$4.call(object, '__wrapped__'),
9445
+ othIsWrapped = othIsObj && hasOwnProperty$4.call(other, '__wrapped__');
9589
9446
 
9590
9447
  if (objIsWrapped || othIsWrapped) {
9591
9448
  var objUnwrapped = objIsWrapped ? object.value() : object,
@@ -9959,10 +9816,10 @@ function createAggregator(setter, initializer) {
9959
9816
  }
9960
9817
 
9961
9818
  /** Used for built-in method references. */
9962
- var objectProto$3 = Object.prototype;
9819
+ var objectProto$4 = Object.prototype;
9963
9820
 
9964
9821
  /** Used to check objects for own properties. */
9965
- var hasOwnProperty$2 = objectProto$3.hasOwnProperty;
9822
+ var hasOwnProperty$3 = objectProto$4.hasOwnProperty;
9966
9823
 
9967
9824
  /**
9968
9825
  * Creates an object composed of keys generated from the results of running
@@ -9987,7 +9844,7 @@ var hasOwnProperty$2 = objectProto$3.hasOwnProperty;
9987
9844
  * // => { '3': 2, '5': 1 }
9988
9845
  */
9989
9846
  var countBy = createAggregator(function(result, value, key) {
9990
- if (hasOwnProperty$2.call(result, key)) {
9847
+ if (hasOwnProperty$3.call(result, key)) {
9991
9848
  ++result[key];
9992
9849
  } else {
9993
9850
  baseAssignValue(result, key, 1);
@@ -9995,10 +9852,10 @@ var countBy = createAggregator(function(result, value, key) {
9995
9852
  });
9996
9853
 
9997
9854
  /** Used for built-in method references. */
9998
- var objectProto$2 = Object.prototype;
9855
+ var objectProto$3 = Object.prototype;
9999
9856
 
10000
9857
  /** Used to check objects for own properties. */
10001
- var hasOwnProperty$1 = objectProto$2.hasOwnProperty;
9858
+ var hasOwnProperty$2 = objectProto$3.hasOwnProperty;
10002
9859
 
10003
9860
  /**
10004
9861
  * Creates an object composed of keys generated from the results of running
@@ -10024,7 +9881,7 @@ var hasOwnProperty$1 = objectProto$2.hasOwnProperty;
10024
9881
  * // => { '3': ['one', 'two'], '5': ['three'] }
10025
9882
  */
10026
9883
  var groupBy = createAggregator(function(result, value, key) {
10027
- if (hasOwnProperty$1.call(result, key)) {
9884
+ if (hasOwnProperty$2.call(result, key)) {
10028
9885
  result[key].push(value);
10029
9886
  } else {
10030
9887
  baseAssignValue(result, key, [value]);
@@ -10241,7 +10098,7 @@ function baseOrderBy(collection, iteratees, orders) {
10241
10098
  if (isArray(iteratee)) {
10242
10099
  return function(value) {
10243
10100
  return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
10244
- }
10101
+ };
10245
10102
  }
10246
10103
  return iteratee;
10247
10104
  });
@@ -10306,11 +10163,130 @@ var sortBy = baseRest(function(collection, iteratees) {
10306
10163
  return baseOrderBy(collection, baseFlatten(iteratees), []);
10307
10164
  });
10308
10165
 
10166
+ const pending = new Map();
10167
+ const inFlight = new Set();
10168
+ // Per-object view of `inFlight`, so a caller (notably `Model.destroy`) can
10169
+ // await the saves for a single object without blocking on unrelated writes.
10170
+ const inFlightByObj = new Map();
10171
+ let unloadListenerAttached = false;
10172
+ /**
10173
+ * Execute a save `run` now and track the resulting promise as in-flight until
10174
+ * it settles, both globally (`inFlight`) and per object (`inFlightByObj`), so
10175
+ * `flushPending({ wait: true })` can await every save and `Model.destroy` can
10176
+ * await just its own.
10177
+ *
10178
+ * @internal
10179
+ * @param obj - The owning model/collection (or `null` when the save isn't tied to one).
10180
+ * A rejection is logged and re-surfaced on `obj`'s `error` event.
10181
+ * Called when a debounce timer fires or a flush forces it.
10182
+ */
10183
+ function fireRun(obj, run) {
10184
+ const p = Promise.resolve(run()).catch((e) => {
10185
+ console.error('Skeletor autoSync save error:', e);
10186
+ // Surface failures that bypassed `options.error` on the model's `error` event,
10187
+ // the same channel storage-layer failures already use. Storage saves route
10188
+ // errors through `options.error` and then resolve, so they never reach this
10189
+ // catch and won't double-emit.
10190
+ obj?.trigger?.('error', obj, e);
10191
+ });
10192
+ inFlight.add(p);
10193
+ let perObj;
10194
+ if (obj) {
10195
+ perObj = inFlightByObj.get(obj);
10196
+ if (!perObj) {
10197
+ perObj = new Set();
10198
+ inFlightByObj.set(obj, perObj);
10199
+ }
10200
+ perObj.add(p);
10201
+ }
10202
+ p.finally(() => {
10203
+ inFlight.delete(p);
10204
+ if (perObj) {
10205
+ perObj.delete(p);
10206
+ if (perObj.size === 0)
10207
+ inFlightByObj.delete(obj);
10208
+ }
10209
+ });
10210
+ }
10211
+ /**
10212
+ * Schedule a debounced auto-save for `obj`. Replaces any pending schedule
10213
+ * for the same object.
10214
+ * @internal
10215
+ */
10216
+ function scheduleAutoSave(obj, run, delay) {
10217
+ const existing = pending.get(obj);
10218
+ if (existing)
10219
+ clearTimeout(existing.timerId);
10220
+ const timerId = setTimeout(() => {
10221
+ pending.delete(obj);
10222
+ fireRun(obj, run);
10223
+ }, delay);
10224
+ pending.set(obj, { timerId, run });
10225
+ }
10226
+ /**
10227
+ * Cancel any pending auto-save for `obj`.
10228
+ *
10229
+ * This only stops a *pending* (not-yet-fired) debounce timer. A save whose
10230
+ * timer has already fired is in flight and beyond cancellation — sequence
10231
+ * against it with {@link awaitInFlightSaves} instead.
10232
+ * @internal
10233
+ */
10234
+ function cancelAutoSave(obj) {
10235
+ const existing = pending.get(obj);
10236
+ if (existing) {
10237
+ clearTimeout(existing.timerId);
10238
+ pending.delete(obj);
10239
+ }
10240
+ }
10241
+ /**
10242
+ * Return a promise that settles once every in-flight auto-save for `obj` has
10243
+ * completed, or `null` when none are in flight. `Model.destroy` uses this to
10244
+ * sequence its delete after a save that has already fired, so a late write
10245
+ * cannot land after the delete and resurrect the record.
10246
+ * @internal
10247
+ */
10248
+ function awaitInFlightSaves(obj) {
10249
+ const set = inFlightByObj.get(obj);
10250
+ if (!set || set.size === 0)
10251
+ return null;
10252
+ return Promise.all([...set]).then(() => undefined);
10253
+ }
10254
+ function flushPending({ storage, wait = false, } = {}) {
10255
+ for (const [obj, { timerId, run }] of pending.entries()) {
10256
+ clearTimeout(timerId);
10257
+ fireRun(obj, run);
10258
+ }
10259
+ pending.clear();
10260
+ if (storage)
10261
+ storage.flushAll();
10262
+ if (wait)
10263
+ return Promise.all([...inFlight]).then(() => undefined);
10264
+ }
10265
+ /**
10266
+ * Lazily attach pagehide/visibilitychange listeners in browser environments
10267
+ * to flush pending writes when the page is hidden/unloading. This is a
10268
+ * best-effort durability measure: the flush initiates writes synchronously but
10269
+ * cannot guarantee an asynchronous backend finishes persisting them before the
10270
+ * page goes away. Called at most once.
10271
+ * @internal
10272
+ */
10273
+ function ensureUnloadListener(storage) {
10274
+ if (unloadListenerAttached || typeof window === 'undefined')
10275
+ return;
10276
+ unloadListenerAttached = true;
10277
+ const flush = () => flushPending({ storage });
10278
+ window.addEventListener('pagehide', flush);
10279
+ window.addEventListener('visibilitychange', () => {
10280
+ if (document.visibilityState === 'hidden')
10281
+ flush();
10282
+ });
10283
+ }
10284
+
10309
10285
  /** Used for built-in method references. */
10310
- var objectProto$1 = Object.prototype;
10286
+ var objectProto$2 = Object.prototype;
10311
10287
 
10312
10288
  /** Used to check objects for own properties. */
10313
- var hasOwnProperty = objectProto$1.hasOwnProperty;
10289
+ var hasOwnProperty$1 = objectProto$2.hasOwnProperty;
10314
10290
 
10315
10291
  /**
10316
10292
  * Assigns own and inherited enumerable string keyed properties of source
@@ -10355,7 +10331,7 @@ var defaults = baseRest(function(object, sources) {
10355
10331
  var value = object[key];
10356
10332
 
10357
10333
  if (value === undefined ||
10358
- (eq(value, objectProto$1[key]) && !hasOwnProperty.call(object, key))) {
10334
+ (eq(value, objectProto$2[key]) && !hasOwnProperty$1.call(object, key))) {
10359
10335
  object[key] = source[key];
10360
10336
  }
10361
10337
  }
@@ -10439,14 +10415,14 @@ function createInverter(setter, toIteratee) {
10439
10415
  }
10440
10416
 
10441
10417
  /** Used for built-in method references. */
10442
- var objectProto = Object.prototype;
10418
+ var objectProto$1 = Object.prototype;
10443
10419
 
10444
10420
  /**
10445
10421
  * Used to resolve the
10446
10422
  * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
10447
10423
  * of values.
10448
10424
  */
10449
- var nativeObjectToString = objectProto.toString;
10425
+ var nativeObjectToString = objectProto$1.toString;
10450
10426
 
10451
10427
  /**
10452
10428
  * Creates an object composed of the inverted keys and values of `object`.
@@ -10617,6 +10593,12 @@ function parent(object, path) {
10617
10593
  return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
10618
10594
  }
10619
10595
 
10596
+ /** Used for built-in method references. */
10597
+ var objectProto = Object.prototype;
10598
+
10599
+ /** Used to check objects for own properties. */
10600
+ var hasOwnProperty = objectProto.hasOwnProperty;
10601
+
10620
10602
  /**
10621
10603
  * The base implementation of `_.unset`.
10622
10604
  *
@@ -10627,8 +10609,34 @@ function parent(object, path) {
10627
10609
  */
10628
10610
  function baseUnset(object, path) {
10629
10611
  path = castPath(path, object);
10630
- object = parent(object, path);
10631
- return object == null || delete object[toKey(last(path))];
10612
+
10613
+ // Prevent prototype pollution:
10614
+ // https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg
10615
+ // https://github.com/lodash/lodash/security/advisories/GHSA-f23m-r3pf-42rh
10616
+ var index = -1,
10617
+ length = path.length;
10618
+
10619
+ if (!length) {
10620
+ return true;
10621
+ }
10622
+
10623
+ while (++index < length) {
10624
+ var key = toKey(path[index]);
10625
+
10626
+ // Always block "__proto__" anywhere in the path if it's not expected
10627
+ if (key === '__proto__' && !hasOwnProperty.call(object, '__proto__')) {
10628
+ return false;
10629
+ }
10630
+
10631
+ // Block constructor/prototype as non-terminal traversal keys to prevent
10632
+ // escaping the object graph into built-in constructors and prototypes.
10633
+ if ((key === 'constructor' || key === 'prototype') && index < length - 1) {
10634
+ return false;
10635
+ }
10636
+ }
10637
+
10638
+ var obj = parent(object, path);
10639
+ return obj == null || delete obj[toKey(last(path))];
10632
10640
  }
10633
10641
 
10634
10642
  /**
@@ -10826,6 +10834,7 @@ var pick = flatRest(function(object, paths) {
10826
10834
  return object == null ? {} : basePick(object, paths);
10827
10835
  });
10828
10836
 
10837
+ var _Model_instances, _Model_computedCache, _Model_computedDefs, _Model_state, _Model_hydrate, _Model_doAutoSave, _Model_updateComputed, _Model_initComputed;
10829
10838
  /**
10830
10839
  * @public
10831
10840
  * **Models** are the basic data object in the framework --
@@ -10840,6 +10849,10 @@ class Model extends EventEmitterObject {
10840
10849
  */
10841
10850
  constructor(attributes, options) {
10842
10851
  super();
10852
+ _Model_instances.add(this);
10853
+ _Model_computedCache.set(this, void 0);
10854
+ _Model_computedDefs.set(this, void 0);
10855
+ _Model_state.set(this, 'constructing');
10843
10856
  this._changing = false;
10844
10857
  this._pending = false;
10845
10858
  this._url = '';
@@ -10857,15 +10870,74 @@ class Model extends EventEmitterObject {
10857
10870
  const default_attrs = result(this, 'defaults');
10858
10871
  attrs = defaults(Object.assign({}, default_attrs, attrs), default_attrs);
10859
10872
  this.set(attrs, options);
10873
+ __classPrivateFieldGet(this, _Model_instances, "m", _Model_initComputed).call(this);
10874
+ this.attrs = new Proxy(this.attributes, {
10875
+ get: (_target, key) => {
10876
+ if (typeof key !== 'symbol' && __classPrivateFieldGet(this, _Model_computedCache, "f") && key in __classPrivateFieldGet(this, _Model_computedCache, "f")) {
10877
+ return __classPrivateFieldGet(this, _Model_computedCache, "f")[key];
10878
+ }
10879
+ return this.attributes[key];
10880
+ },
10881
+ set: (_target, key, value) => {
10882
+ this.set(key, value);
10883
+ return true;
10884
+ },
10885
+ });
10860
10886
  this.initialize.apply(this, arguments);
10861
10887
  // Reset changed after initial set
10862
10888
  this.changed = {};
10889
+ // When autoSync is on, `initialized` is always a Promise so callers can
10890
+ // uniformly `await model.initialized`. It only hydrates from storage when
10891
+ // there's something to load (storage configured and the model isn't new);
10892
+ // otherwise it's already ready and resolves immediately.
10893
+ if (this.autoSync) {
10894
+ if (getStorage(this) && !this.isNew()) {
10895
+ __classPrivateFieldSet(this, _Model_state, 'hydrating', "f");
10896
+ this.initialized = __classPrivateFieldGet(this, _Model_instances, "m", _Model_hydrate).call(this);
10897
+ }
10898
+ else {
10899
+ __classPrivateFieldSet(this, _Model_state, 'ready', "f");
10900
+ this.initialized = Promise.resolve();
10901
+ }
10902
+ }
10903
+ else {
10904
+ __classPrivateFieldSet(this, _Model_state, 'ready', "f");
10905
+ }
10906
+ }
10907
+ /**
10908
+ * The canonical storage accessor. Set to a `PersistentStorage` instance
10909
+ * to enable local persistence for this model.
10910
+ */
10911
+ get storage() {
10912
+ return this._storage;
10863
10913
  }
10864
- set browserStorage(storage) {
10865
- this._browserStorage = storage;
10914
+ set storage(s) {
10915
+ this._storage = s;
10916
+ PersistentStorage.register(s);
10866
10917
  }
10918
+ /**
10919
+ * @deprecated Use `storage` instead.
10920
+ */
10867
10921
  get browserStorage() {
10868
- return this._browserStorage;
10922
+ return this._storage;
10923
+ }
10924
+ set browserStorage(s) {
10925
+ warnBrowserStorageDeprecation(this);
10926
+ this.storage = s;
10927
+ }
10928
+ /**
10929
+ * Override to enable automatic persistence. When true, any `set()` call
10930
+ * that changes attributes will schedule a debounced save to `storage`, and
10931
+ * the model will auto-hydrate from storage on construction.
10932
+ */
10933
+ get autoSync() {
10934
+ return false;
10935
+ }
10936
+ /**
10937
+ * Debounce delay (ms) for auto-save writes. Override to tune.
10938
+ */
10939
+ get autoSyncDelay() {
10940
+ return 100;
10869
10941
  }
10870
10942
  /**
10871
10943
  * The default name for the JSON `id` attribute is `"id"`. MongoDB and
@@ -10901,6 +10973,17 @@ class Model extends EventEmitterObject {
10901
10973
  defaults() {
10902
10974
  return {};
10903
10975
  }
10976
+ /**
10977
+ * Declare computed properties. Override in subclasses to define properties
10978
+ * that derive their value from other attributes. Each entry specifies the
10979
+ * attribute keys it depends on (`deps`) and a function (`fn`) that receives
10980
+ * the model and returns the computed value. The value is cached and
10981
+ * recalculated automatically when any dep changes, firing a `change:key`
10982
+ * event.
10983
+ */
10984
+ get computed() {
10985
+ return {};
10986
+ }
10904
10987
  /**
10905
10988
  * Return a copy of the model's `attributes` object.
10906
10989
  */
@@ -10914,9 +10997,12 @@ class Model extends EventEmitterObject {
10914
10997
  return getSyncMethod(model)(method, model, options);
10915
10998
  }
10916
10999
  /**
10917
- * Get the value of an attribute.
11000
+ * Get the value of an attribute, or a computed property.
10918
11001
  */
10919
11002
  get(attr) {
11003
+ if (__classPrivateFieldGet(this, _Model_computedCache, "f") && attr in __classPrivateFieldGet(this, _Model_computedCache, "f")) {
11004
+ return __classPrivateFieldGet(this, _Model_computedCache, "f")[attr];
11005
+ }
10920
11006
  return this.attributes[attr];
10921
11007
  }
10922
11008
  keys() {
@@ -10981,6 +11067,11 @@ class Model extends EventEmitterObject {
10981
11067
  attrs[key] = val;
10982
11068
  }
10983
11069
  options = options || {};
11070
+ // Guard must come after arg normalization: when called as set(obj, opts),
11071
+ // fromStorage lives in `val` (second arg), not `options` (third arg).
11072
+ if (this.autoSync && __classPrivateFieldGet(this, _Model_state, "f") === 'hydrating' && !options.fromStorage) {
11073
+ throw new Error(`Skeletor: set() called on an autoSync model before initialized resolved. Await model.initialized first.`);
11074
+ }
10984
11075
  // Run validation.
10985
11076
  if (!this._validate(attrs, options))
10986
11077
  return null;
@@ -11021,6 +11112,14 @@ class Model extends EventEmitterObject {
11021
11112
  this.trigger('change:' + changes[i], this, current[changes[i]], options);
11022
11113
  }
11023
11114
  }
11115
+ // Recalculate computed properties whose deps changed.
11116
+ if (changes.length && __classPrivateFieldGet(this, _Model_computedDefs, "f")) {
11117
+ for (const [key, def] of Object.entries(__classPrivateFieldGet(this, _Model_computedDefs, "f"))) {
11118
+ if (def.deps.some((dep) => changes.includes(dep))) {
11119
+ __classPrivateFieldGet(this, _Model_instances, "m", _Model_updateComputed).call(this, key, def, silent, options);
11120
+ }
11121
+ }
11122
+ }
11024
11123
  if (changing)
11025
11124
  return this;
11026
11125
  if (!silent) {
@@ -11034,6 +11133,17 @@ class Model extends EventEmitterObject {
11034
11133
  }
11035
11134
  this._pending = false;
11036
11135
  this._changing = false;
11136
+ // Auto-save: schedule a debounced write when autoSync is on and there
11137
+ // were actual changes that originated from application code (not a
11138
+ // storage read or an explicit noAutoSave call).
11139
+ if (__classPrivateFieldGet(this, _Model_state, "f") === 'ready' &&
11140
+ this.autoSync &&
11141
+ getStorage(this) &&
11142
+ changes.length &&
11143
+ !options.fromStorage &&
11144
+ !options.noAutoSave) {
11145
+ scheduleAutoSave(this, () => __classPrivateFieldGet(this, _Model_instances, "m", _Model_doAutoSave).call(this), this.autoSyncDelay);
11146
+ }
11037
11147
  return this;
11038
11148
  }
11039
11149
  /**
@@ -11108,16 +11218,48 @@ class Model extends EventEmitterObject {
11108
11218
  fetch(options = {}) {
11109
11219
  options = Object.assign({ parse: true }, options);
11110
11220
  const success = options.success;
11221
+ const promise = options.promise ? getResolveablePromise() : undefined;
11222
+ // Tracks whether sync invoked one of the callbacks. A sync may instead
11223
+ // settle its returned promise; the `.then`/`.catch` below bridges that to
11224
+ // the callbacks so the fetch promise never hangs. The flag is set
11225
+ // synchronously inside each callback (before sync's promise resolves), so
11226
+ // it's reliable by the time those handlers run.
11227
+ let settled = false;
11111
11228
  options.success = (resp) => {
11229
+ settled = true;
11112
11230
  const serverAttrs = options.parse ? this.parse(resp, options) : resp;
11113
- if (!this.set(serverAttrs, options))
11231
+ // fromStorage prevents the set() from triggering auto-save on reads
11232
+ if (!this.set(serverAttrs, Object.assign({}, options, { fromStorage: true })))
11114
11233
  return false;
11115
11234
  if (success)
11116
11235
  success.call(options.context, this, resp, options);
11117
11236
  this.trigger('sync', this, resp, options);
11237
+ promise && promise.resolve(resp);
11118
11238
  };
11119
- wrapError(this, options);
11120
- return this.sync('read', this, options);
11239
+ wrapError(this, options, promise);
11240
+ if (promise) {
11241
+ const onError = options.error;
11242
+ options.error = (resp) => {
11243
+ settled = true;
11244
+ onError(resp);
11245
+ };
11246
+ }
11247
+ const result = this.sync('read', this, options);
11248
+ if (promise) {
11249
+ Promise.resolve(result).then(
11250
+ // A sync that resolves its promise without invoking options.success:
11251
+ // treat the resolved value as the response, so the model is still
11252
+ // merged and the promise settles instead of hanging.
11253
+ (value) => {
11254
+ if (!settled)
11255
+ options.success(value);
11256
+ },
11257
+ // A sync that rejects instead of invoking options.error; settling
11258
+ // twice is a harmless no-op.
11259
+ (e) => promise.reject(e));
11260
+ return promise;
11261
+ }
11262
+ return result;
11121
11263
  }
11122
11264
  /**
11123
11265
  * Set a hash of model attributes, and sync the model to the server.
@@ -11194,6 +11336,7 @@ class Model extends EventEmitterObject {
11194
11336
  * If `wait: true` is passed, waits for the server to respond before removal.
11195
11337
  */
11196
11338
  destroy(options) {
11339
+ cancelAutoSave(this);
11197
11340
  options = options ? clone(options) : {};
11198
11341
  const success = options.success;
11199
11342
  const wait = options.wait;
@@ -11209,13 +11352,25 @@ class Model extends EventEmitterObject {
11209
11352
  if (!this.isNew())
11210
11353
  this.trigger('sync', this, resp, options);
11211
11354
  };
11355
+ // A debounced auto-save may already have fired and be in flight.
11356
+ // cancelAutoSave() above only stops a *pending* timer, so sequence the
11357
+ // delete after any in-flight save; otherwise the late write could land
11358
+ // after the delete and resurrect the record. Capture the collection now,
11359
+ // the optimistic in-memory removal below nulls `model.collection` before
11360
+ // the deferred sync runs, but the storage layer still needs it to drop
11361
+ // this id from the collection's persisted index.
11362
+ const inFlightSave = awaitInFlightSaves(this);
11363
+ if (inFlightSave && this.collection)
11364
+ options.collection = this.collection;
11212
11365
  let xhr = false;
11213
11366
  if (this.isNew()) {
11214
11367
  defer(options.success);
11215
11368
  }
11216
11369
  else {
11217
11370
  wrapError(this, options);
11218
- xhr = this.sync('delete', this, options);
11371
+ xhr = inFlightSave
11372
+ ? inFlightSave.then(() => this.sync('delete', this, options))
11373
+ : this.sync('delete', this, options);
11219
11374
  }
11220
11375
  if (!wait)
11221
11376
  destroy();
@@ -11263,6 +11418,14 @@ class Model extends EventEmitterObject {
11263
11418
  isValid(options) {
11264
11419
  return this._validate({}, Object.assign({}, options, { validate: true }));
11265
11420
  }
11421
+ subscribe(eventOrCallback, callback, context) {
11422
+ if (typeof eventOrCallback === 'function') {
11423
+ const cb = (model) => eventOrCallback(model, this.changed);
11424
+ this.on('change', cb);
11425
+ return () => this.off('change', cb);
11426
+ }
11427
+ return super.subscribe(eventOrCallback, callback, context);
11428
+ }
11266
11429
  /**
11267
11430
  * Run validation against the next complete set of model attributes,
11268
11431
  * returning `true` if all is well. Otherwise, fire an `"invalid"` event.
@@ -11278,8 +11441,43 @@ class Model extends EventEmitterObject {
11278
11441
  return false;
11279
11442
  }
11280
11443
  }
11444
+ _Model_computedCache = new WeakMap(), _Model_computedDefs = new WeakMap(), _Model_state = new WeakMap(), _Model_instances = new WeakSet(), _Model_hydrate = async function _Model_hydrate() {
11445
+ ensureUnloadListener(PersistentStorage);
11446
+ try {
11447
+ await this.fetch({ fromStorage: true, promise: true });
11448
+ }
11449
+ catch (e) {
11450
+ // 'Record Not Found' is a normal first-run state (nothing stored yet);
11451
+ // keep the initial attributes and resolve. Re-throw anything else.
11452
+ if (e !== 'Record Not Found')
11453
+ throw e;
11454
+ }
11455
+ finally {
11456
+ __classPrivateFieldSet(this, _Model_state, 'ready', "f");
11457
+ }
11458
+ }, _Model_doAutoSave = function _Model_doAutoSave() {
11459
+ return this.save(null, { noAutoSave: true });
11460
+ }, _Model_updateComputed = function _Model_updateComputed(key, def, silent, options) {
11461
+ const newVal = def.fn(this);
11462
+ if (!isEqual(__classPrivateFieldGet(this, _Model_computedCache, "f")[key], newVal)) {
11463
+ __classPrivateFieldGet(this, _Model_computedCache, "f")[key] = newVal;
11464
+ if (!silent) {
11465
+ this.changed[key] = newVal;
11466
+ this.trigger('change:' + key, this, newVal, options);
11467
+ }
11468
+ }
11469
+ }, _Model_initComputed = function _Model_initComputed() {
11470
+ const defs = result(this, 'computed');
11471
+ if (!defs || isEmpty(defs))
11472
+ return;
11473
+ __classPrivateFieldSet(this, _Model_computedDefs, defs, "f");
11474
+ __classPrivateFieldSet(this, _Model_computedCache, {}, "f");
11475
+ for (const [key, def] of Object.entries(defs)) {
11476
+ __classPrivateFieldGet(this, _Model_computedCache, "f")[key] = def.fn(this);
11477
+ }
11478
+ };
11281
11479
 
11282
- var _a;
11480
+ var _Collection_instances, _Collection_hydrate, _a;
11283
11481
  // Default options for `Collection#set`.
11284
11482
  const setOptions = { add: true, remove: true, merge: true };
11285
11483
  const addOptions = { add: true, remove: false };
@@ -11300,6 +11498,7 @@ class Collection extends EventEmitterObject {
11300
11498
  */
11301
11499
  constructor(models, options) {
11302
11500
  super();
11501
+ _Collection_instances.add(this);
11303
11502
  this._url = '';
11304
11503
  /**
11305
11504
  * @public
@@ -11317,6 +11516,12 @@ class Collection extends EventEmitterObject {
11317
11516
  if (models)
11318
11517
  this.reset(models, Object.assign({ silent: true }, options));
11319
11518
  this[Symbol.iterator] = this.values;
11519
+ // When autoSync is on, `initialized` is always a Promise so callers can
11520
+ // uniformly `await collection.initialized`; it resolves immediately when
11521
+ // there's no storage to hydrate from.
11522
+ if (this.autoSync) {
11523
+ this.initialized = getStorage(this) ? __classPrivateFieldGet(this, _Collection_instances, "m", _Collection_hydrate).call(this) : Promise.resolve();
11524
+ }
11320
11525
  }
11321
11526
  get comparator() {
11322
11527
  return this._comparator;
@@ -11324,11 +11529,40 @@ class Collection extends EventEmitterObject {
11324
11529
  set comparator(c) {
11325
11530
  this._comparator = c;
11326
11531
  }
11327
- set browserStorage(storage) {
11328
- this._browserStorage = storage;
11532
+ /**
11533
+ * The canonical storage accessor. Set to a `PersistentStorage` instance
11534
+ * to enable local persistence for this collection.
11535
+ */
11536
+ get storage() {
11537
+ return this._storage;
11538
+ }
11539
+ set storage(s) {
11540
+ this._storage = s;
11541
+ PersistentStorage.register(s);
11329
11542
  }
11543
+ /**
11544
+ * @deprecated Use `storage` instead.
11545
+ */
11330
11546
  get browserStorage() {
11331
- return this._browserStorage;
11547
+ return this._storage;
11548
+ }
11549
+ set browserStorage(s) {
11550
+ warnBrowserStorageDeprecation(this);
11551
+ this.storage = s;
11552
+ }
11553
+ /**
11554
+ * Override to return `true` to automatically load the collection from
11555
+ * storage on construction. Await `initialized` to know when hydration
11556
+ * is complete.
11557
+ *
11558
+ * Note: collection `autoSync` is hydrate-only. Unlike `Model`, it does
11559
+ * **not** schedule auto-saves when the collection changes (`add`/`remove`/
11560
+ * `reset`). Persisting members is each model's responsibility — enable
11561
+ * `autoSync` on the contained model class and every model writes its own
11562
+ * record. A collection-level write would be redundant with that.
11563
+ */
11564
+ get autoSync() {
11565
+ return false;
11332
11566
  }
11333
11567
  /**
11334
11568
  * The default model for a collection is just a **Model**.
@@ -11523,7 +11757,7 @@ class Collection extends EventEmitterObject {
11523
11757
  }));
11524
11758
  });
11525
11759
  }));
11526
- await this.browserStorage?.clear();
11760
+ await getStorage(this)?.clear();
11527
11761
  this.reset();
11528
11762
  }
11529
11763
  /**
@@ -11761,17 +11995,47 @@ class Collection extends EventEmitterObject {
11761
11995
  const success = options.success;
11762
11996
  // eslint-disable-next-line @typescript-eslint/no-this-alias
11763
11997
  const collection = this;
11764
- const promise = options.promise && getResolveablePromise();
11998
+ const promise = options.promise ? getResolveablePromise() : undefined;
11999
+ // Tracks whether sync invoked one of the callbacks. A sync may instead
12000
+ // settle its returned promise; the `.then`/`.catch` below bridges that to
12001
+ // the callbacks so the fetch promise never hangs. The flag is set
12002
+ // synchronously inside each callback (before sync's promise resolves), so
12003
+ // it's reliable by the time those handlers run.
12004
+ let settled = false;
11765
12005
  options.success = function (resp) {
12006
+ settled = true;
11766
12007
  const method = options.reset ? 'reset' : 'set';
11767
- collection[method](resp, options);
12008
+ // fromStorage prevents individual model set() calls from triggering auto-save on reads
12009
+ collection[method](resp, Object.assign({}, options, { fromStorage: true }));
11768
12010
  if (success)
11769
12011
  success.call(options.context, collection, resp, options);
11770
12012
  promise && promise.resolve();
11771
12013
  collection.trigger('sync', collection, resp, options);
11772
12014
  };
11773
- wrapError(this, options);
11774
- return promise ? promise : this.sync('read', this, options);
12015
+ wrapError(this, options, promise);
12016
+ if (promise) {
12017
+ const onError = options.error;
12018
+ options.error = (resp) => {
12019
+ settled = true;
12020
+ onError(resp);
12021
+ };
12022
+ }
12023
+ const result = this.sync('read', this, options);
12024
+ if (promise) {
12025
+ Promise.resolve(result).then(
12026
+ // A sync that resolves its promise without invoking options.success:
12027
+ // treat the resolved value as the response, so the collection is still
12028
+ // populated and the promise settles instead of hanging.
12029
+ (value) => {
12030
+ if (!settled)
12031
+ options.success(value);
12032
+ },
12033
+ // A sync that rejects instead of invoking options.error; settling
12034
+ // twice is a harmless no-op.
12035
+ (e) => promise.reject(e));
12036
+ return promise;
12037
+ }
12038
+ return result;
11775
12039
  }
11776
12040
  /**
11777
12041
  * Create a new instance of a model in this collection. Add the model to the
@@ -11815,6 +12079,14 @@ class Collection extends EventEmitterObject {
11815
12079
  return preparedModel;
11816
12080
  }
11817
12081
  }
12082
+ subscribe(eventOrCallback, callback, context) {
12083
+ if (typeof eventOrCallback === 'function') {
12084
+ const cb = () => eventOrCallback(this);
12085
+ this.on('update reset sort', cb);
12086
+ return () => this.off('update reset sort', cb);
12087
+ }
12088
+ return super.subscribe(eventOrCallback, callback, context);
12089
+ }
11818
12090
  /**
11819
12091
  * **parse** converts a response into a list of models to be added to the
11820
12092
  * collection. The default implementation is just to pass it through.
@@ -11952,7 +12224,12 @@ class Collection extends EventEmitterObject {
11952
12224
  this.trigger.apply(this, arguments);
11953
12225
  }
11954
12226
  }
11955
- _a = Symbol.iterator;
12227
+ _Collection_instances = new WeakSet(), _Collection_hydrate = async function _Collection_hydrate() {
12228
+ ensureUnloadListener(PersistentStorage);
12229
+ // findAll() returns [] for an empty store, so a first-run collection
12230
+ // resolves rather than erroring the way a model fetch-by-id would.
12231
+ await this.fetch({ fromStorage: true, promise: true });
12232
+ }, _a = Symbol.iterator;
11956
12233
  // This "enum" defines the three possible kinds of values which can be emitted
11957
12234
  // by a CollectionIterator that correspond to the values(), keys() and entries()
11958
12235
  // methods on Collection, respectively.
@@ -12041,6 +12318,11 @@ function noConflict() {
12041
12318
  }
12042
12319
  skeletor.noConflict = noConflict;
12043
12320
  root.Skeletor = skeletor;
12321
+ /**
12322
+ * @deprecated Use `PersistentStorage` instead.
12323
+ * @public
12324
+ */
12325
+ const BrowserStorage = PersistentStorage;
12044
12326
 
12045
- export { BrowserStorage, Collection, EventEmitter, Model, skeletor as default, noConflict, sync };
12327
+ export { BrowserStorage, Collection, EventEmitter, Model, PersistentStorage, skeletor as default, getStorage, noConflict, sync };
12046
12328
  //# sourceMappingURL=skeletor.esm.js.map