@converse/skeletor 3.0.1 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +330 -38
- package/dist/skeletor.d.ts +200 -56
- package/dist/skeletor.esm.js +747 -457
- package/dist/skeletor.esm.js.map +1 -1
- package/dist/skeletor.js +748 -456
- package/dist/skeletor.js.map +1 -1
- package/dist/skeletor.min.js +6 -19
- package/dist/skeletor.node.js +12507 -0
- package/dist/skeletor.node.mjs +12494 -0
- package/package.json +27 -10
- package/src/autosync.ts +156 -0
- package/src/collection.ts +140 -35
- package/src/drivers/helpers.ts +61 -0
- package/src/drivers/nodeSQLiteStorage.ts +162 -0
- package/src/drivers/sessionStorage.ts +16 -22
- package/src/drivers/types.ts +25 -0
- package/src/eventemitter.ts +9 -0
- package/src/helpers.ts +57 -10
- package/src/index.node.ts +16 -0
- package/src/index.ts +11 -3
- package/src/model.ts +254 -13
- package/src/storage.ts +93 -36
- package/src/types.ts +34 -9
- package/src/utils/events.ts +6 -6
package/dist/skeletor.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Used for built-in method references. */
|
|
2
|
-
var objectProto$
|
|
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$
|
|
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$
|
|
36
|
+
var objectProto$l = Object.prototype;
|
|
37
37
|
|
|
38
38
|
/** Used to check objects for own properties. */
|
|
39
|
-
var 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$
|
|
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$
|
|
74
|
+
var objectProto$k = Object.prototype;
|
|
75
75
|
|
|
76
76
|
/** Used to check objects for own properties. */
|
|
77
|
-
var 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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
441
|
+
var objectProto$h = Object.prototype;
|
|
442
442
|
|
|
443
443
|
/** Used to check objects for own properties. */
|
|
444
|
-
var hasOwnProperty$
|
|
444
|
+
var hasOwnProperty$f = objectProto$h.hasOwnProperty;
|
|
445
445
|
|
|
446
446
|
/** Built-in value references. */
|
|
447
|
-
var propertyIsEnumerable$1 = objectProto$
|
|
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$
|
|
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$
|
|
733
|
+
var objectProto$g = Object.prototype;
|
|
734
734
|
|
|
735
735
|
/** Used to check objects for own properties. */
|
|
736
|
-
var 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$
|
|
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$
|
|
839
|
+
var objectProto$f = Object.prototype;
|
|
840
840
|
|
|
841
841
|
/** Used to check objects for own properties. */
|
|
842
|
-
var 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$
|
|
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$
|
|
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$
|
|
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
|
|
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
|
|
1725
|
-
var SERIALIZED_MARKER_LENGTH
|
|
1726
|
-
var TYPE_SERIALIZED_MARKER_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
|
|
1729
|
-
function stringToBuffer
|
|
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
|
|
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$
|
|
1809
|
+
function serialize$1(value, callback) {
|
|
1784
1810
|
var valueType = '';
|
|
1785
1811
|
if (value) {
|
|
1786
|
-
valueType = toString
|
|
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
|
|
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
|
|
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
|
|
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$
|
|
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
|
|
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
|
|
1878
|
-
var type = value.substring(SERIALIZED_MARKER_LENGTH
|
|
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
|
|
1883
|
-
var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX
|
|
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
|
|
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
|
|
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$
|
|
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
|
|
2002
|
-
deserialize: deserialize$
|
|
2003
|
-
serialize: serialize$
|
|
2004
|
-
stringToBuffer: stringToBuffer
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
2521
|
+
var objectProto$e = Object.prototype;
|
|
2496
2522
|
|
|
2497
2523
|
/** Used to check objects for own properties. */
|
|
2498
|
-
var 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$
|
|
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$
|
|
2545
|
+
var objectProto$d = Object.prototype;
|
|
2520
2546
|
|
|
2521
2547
|
/** Used to check objects for own properties. */
|
|
2522
|
-
var 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$
|
|
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$
|
|
2839
|
+
var objectProto$c = Object.prototype;
|
|
2814
2840
|
|
|
2815
2841
|
/** Used to check objects for own properties. */
|
|
2816
|
-
var 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$
|
|
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$
|
|
2929
|
+
var objectProto$b = Object.prototype;
|
|
2904
2930
|
|
|
2905
2931
|
/** Used to check objects for own properties. */
|
|
2906
|
-
var 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$
|
|
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$
|
|
3094
|
+
var objectProto$a = Object.prototype;
|
|
3069
3095
|
|
|
3070
3096
|
/** Built-in value references. */
|
|
3071
|
-
var propertyIsEnumerable = objectProto$
|
|
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$
|
|
3224
|
+
var objectProto$9 = Object.prototype;
|
|
3199
3225
|
|
|
3200
3226
|
/** Used to check objects for own properties. */
|
|
3201
|
-
var 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$
|
|
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$
|
|
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$
|
|
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$
|
|
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
|
|
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
|
-
|
|
7388
|
-
|
|
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
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
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
|
|
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;
|
|
7499
|
-
}
|
|
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];
|
|
7516
|
-
}
|
|
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) + '==';
|
|
7523
|
-
}
|
|
7524
|
-
|
|
7525
|
-
return base64String;
|
|
7422
|
+
return val;
|
|
7423
|
+
});
|
|
7526
7424
|
}
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
// we store binary data with localStorage.
|
|
7531
|
-
function serialize$1(value, callback) {
|
|
7532
|
-
var valueType = '';
|
|
7533
|
-
if (value) {
|
|
7534
|
-
valueType = toString.call(value);
|
|
7425
|
+
function serialize(value, callback) {
|
|
7426
|
+
try {
|
|
7427
|
+
callback(serializeSync(value), null);
|
|
7535
7428
|
}
|
|
7536
|
-
|
|
7537
|
-
|
|
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
|
-
}
|
|
7429
|
+
catch (e) {
|
|
7430
|
+
callback('', e);
|
|
7606
7431
|
}
|
|
7607
7432
|
}
|
|
7608
|
-
|
|
7609
|
-
|
|
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
|
-
}
|
|
7433
|
+
function deserialize(value) {
|
|
7434
|
+
return JSON.parse(value);
|
|
7672
7435
|
}
|
|
7673
7436
|
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
7619
|
+
chainCallback(Promise.reject(e), callback);
|
|
7863
7620
|
}
|
|
7864
7621
|
});
|
|
7865
7622
|
});
|
|
7866
7623
|
}
|
|
7867
|
-
function dropInstance(
|
|
7868
|
-
callback = getCallback
|
|
7869
|
-
options = (typeof
|
|
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
|
-
|
|
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$
|
|
8133
|
+
var objectProto$7 = Object.prototype;
|
|
8377
8134
|
|
|
8378
8135
|
/** Used to check objects for own properties. */
|
|
8379
|
-
var 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$
|
|
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$
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,20 @@ 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 = PersistentStorage.nodeStorage;
|
|
8669
|
+
if (!NodeSQLiteStorage) {
|
|
8670
|
+
throw new Error("Skeletor.storage: the 'node' storage type is only available in Node.js builds. " +
|
|
8671
|
+
"Import from '@converse/skeletor/node' instead of '@converse/skeletor'.");
|
|
8672
|
+
}
|
|
8673
|
+
this.store = new NodeSQLiteStorage(this.name);
|
|
8674
|
+
if (batchedWrites) {
|
|
8675
|
+
this.store.debouncedSetItems = mergebounce((items) => this.store.setItems(items), 50, {
|
|
8676
|
+
'promise': true,
|
|
8677
|
+
});
|
|
8678
|
+
}
|
|
8679
|
+
return;
|
|
8680
|
+
}
|
|
8825
8681
|
else if (type !== 'indexed') {
|
|
8826
8682
|
throw new Error('Skeletor.storage: No storage type was specified');
|
|
8827
8683
|
}
|
|
@@ -8838,6 +8694,7 @@ class BrowserStorage {
|
|
|
8838
8694
|
}
|
|
8839
8695
|
}
|
|
8840
8696
|
async clear() {
|
|
8697
|
+
await this.storeInitialized;
|
|
8841
8698
|
await this.store.removeItem(this.name).catch((e) => console.error(e));
|
|
8842
8699
|
const re = new RegExp(`^${this.name}-`);
|
|
8843
8700
|
const keys = await this.store.keys();
|
|
@@ -8852,12 +8709,16 @@ class BrowserStorage {
|
|
|
8852
8709
|
// We get the collection (and if necessary the model attribute.
|
|
8853
8710
|
// Waiting for storeInitialized will cause another iteration of
|
|
8854
8711
|
// the event loop, after which the collection reference will
|
|
8855
|
-
// be removed from the model.
|
|
8856
|
-
|
|
8712
|
+
// be removed from the model. `options.collection` lets a deferred
|
|
8713
|
+
// delete (sequenced behind an in-flight auto-save by Model.destroy)
|
|
8714
|
+
// supply the collection captured before its optimistic removal.
|
|
8715
|
+
const collection = options.collection ?? model.collection;
|
|
8857
8716
|
if (['patch', 'update'].includes(method)) {
|
|
8858
8717
|
new_attributes = cloneDeep(model.attributes);
|
|
8859
8718
|
}
|
|
8860
|
-
await
|
|
8719
|
+
// Skip `await` if not necessary to allow for sync flushing
|
|
8720
|
+
if (!that.storeReady)
|
|
8721
|
+
await that.storeInitialized;
|
|
8861
8722
|
try {
|
|
8862
8723
|
const original_attributes = model.attributes;
|
|
8863
8724
|
switch (method) {
|
|
@@ -9012,8 +8873,12 @@ class BrowserStorage {
|
|
|
9012
8873
|
return this.name + '-' + id;
|
|
9013
8874
|
}
|
|
9014
8875
|
}
|
|
9015
|
-
|
|
9016
|
-
|
|
8876
|
+
// The Node.js SQLite storage driver. Left null in browser builds so the
|
|
8877
|
+
// node-only driver (and its `node:sqlite` import) never enters the browser
|
|
8878
|
+
// bundle; the `@converse/skeletor/node` entry sets it.
|
|
8879
|
+
PersistentStorage.nodeStorage = null;
|
|
8880
|
+
PersistentStorage.sessionStorageInitialized = localForage.defineDriver(sessionStorageWrapper);
|
|
8881
|
+
PersistentStorage.localForage = localForage;
|
|
9017
8882
|
|
|
9018
8883
|
/** Used to compose bitmasks for cloning. */
|
|
9019
8884
|
var CLONE_SYMBOLS_FLAG$1 = 4;
|
|
@@ -9163,7 +9028,7 @@ function setCacheAdd(value) {
|
|
|
9163
9028
|
* @name has
|
|
9164
9029
|
* @memberOf SetCache
|
|
9165
9030
|
* @param {*} value The value to search for.
|
|
9166
|
-
* @returns {
|
|
9031
|
+
* @returns {boolean} Returns `true` if `value` is found, else `false`.
|
|
9167
9032
|
*/
|
|
9168
9033
|
function setCacheHas(value) {
|
|
9169
9034
|
return this.__data__.has(value);
|
|
@@ -9446,10 +9311,10 @@ function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
|
|
|
9446
9311
|
var COMPARE_PARTIAL_FLAG$3 = 1;
|
|
9447
9312
|
|
|
9448
9313
|
/** Used for built-in method references. */
|
|
9449
|
-
var objectProto$
|
|
9314
|
+
var objectProto$6 = Object.prototype;
|
|
9450
9315
|
|
|
9451
9316
|
/** Used to check objects for own properties. */
|
|
9452
|
-
var hasOwnProperty$
|
|
9317
|
+
var hasOwnProperty$5 = objectProto$6.hasOwnProperty;
|
|
9453
9318
|
|
|
9454
9319
|
/**
|
|
9455
9320
|
* A specialized version of `baseIsEqualDeep` for objects with support for
|
|
@@ -9477,7 +9342,7 @@ function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
|
|
|
9477
9342
|
var index = objLength;
|
|
9478
9343
|
while (index--) {
|
|
9479
9344
|
var key = objProps[index];
|
|
9480
|
-
if (!(isPartial ? key in other : hasOwnProperty$
|
|
9345
|
+
if (!(isPartial ? key in other : hasOwnProperty$5.call(other, key))) {
|
|
9481
9346
|
return false;
|
|
9482
9347
|
}
|
|
9483
9348
|
}
|
|
@@ -9538,10 +9403,10 @@ var argsTag = '[object Arguments]',
|
|
|
9538
9403
|
objectTag = '[object Object]';
|
|
9539
9404
|
|
|
9540
9405
|
/** Used for built-in method references. */
|
|
9541
|
-
var objectProto$
|
|
9406
|
+
var objectProto$5 = Object.prototype;
|
|
9542
9407
|
|
|
9543
9408
|
/** Used to check objects for own properties. */
|
|
9544
|
-
var hasOwnProperty$
|
|
9409
|
+
var hasOwnProperty$4 = objectProto$5.hasOwnProperty;
|
|
9545
9410
|
|
|
9546
9411
|
/**
|
|
9547
9412
|
* A specialized version of `baseIsEqual` for arrays and objects which performs
|
|
@@ -9584,8 +9449,8 @@ function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
|
|
|
9584
9449
|
: equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
|
|
9585
9450
|
}
|
|
9586
9451
|
if (!(bitmask & COMPARE_PARTIAL_FLAG$2)) {
|
|
9587
|
-
var objIsWrapped = objIsObj && hasOwnProperty$
|
|
9588
|
-
othIsWrapped = othIsObj && hasOwnProperty$
|
|
9452
|
+
var objIsWrapped = objIsObj && hasOwnProperty$4.call(object, '__wrapped__'),
|
|
9453
|
+
othIsWrapped = othIsObj && hasOwnProperty$4.call(other, '__wrapped__');
|
|
9589
9454
|
|
|
9590
9455
|
if (objIsWrapped || othIsWrapped) {
|
|
9591
9456
|
var objUnwrapped = objIsWrapped ? object.value() : object,
|
|
@@ -9959,10 +9824,10 @@ function createAggregator(setter, initializer) {
|
|
|
9959
9824
|
}
|
|
9960
9825
|
|
|
9961
9826
|
/** Used for built-in method references. */
|
|
9962
|
-
var objectProto$
|
|
9827
|
+
var objectProto$4 = Object.prototype;
|
|
9963
9828
|
|
|
9964
9829
|
/** Used to check objects for own properties. */
|
|
9965
|
-
var hasOwnProperty$
|
|
9830
|
+
var hasOwnProperty$3 = objectProto$4.hasOwnProperty;
|
|
9966
9831
|
|
|
9967
9832
|
/**
|
|
9968
9833
|
* Creates an object composed of keys generated from the results of running
|
|
@@ -9987,7 +9852,7 @@ var hasOwnProperty$2 = objectProto$3.hasOwnProperty;
|
|
|
9987
9852
|
* // => { '3': 2, '5': 1 }
|
|
9988
9853
|
*/
|
|
9989
9854
|
var countBy = createAggregator(function(result, value, key) {
|
|
9990
|
-
if (hasOwnProperty$
|
|
9855
|
+
if (hasOwnProperty$3.call(result, key)) {
|
|
9991
9856
|
++result[key];
|
|
9992
9857
|
} else {
|
|
9993
9858
|
baseAssignValue(result, key, 1);
|
|
@@ -9995,10 +9860,10 @@ var countBy = createAggregator(function(result, value, key) {
|
|
|
9995
9860
|
});
|
|
9996
9861
|
|
|
9997
9862
|
/** Used for built-in method references. */
|
|
9998
|
-
var objectProto$
|
|
9863
|
+
var objectProto$3 = Object.prototype;
|
|
9999
9864
|
|
|
10000
9865
|
/** Used to check objects for own properties. */
|
|
10001
|
-
var hasOwnProperty$
|
|
9866
|
+
var hasOwnProperty$2 = objectProto$3.hasOwnProperty;
|
|
10002
9867
|
|
|
10003
9868
|
/**
|
|
10004
9869
|
* Creates an object composed of keys generated from the results of running
|
|
@@ -10024,7 +9889,7 @@ var hasOwnProperty$1 = objectProto$2.hasOwnProperty;
|
|
|
10024
9889
|
* // => { '3': ['one', 'two'], '5': ['three'] }
|
|
10025
9890
|
*/
|
|
10026
9891
|
var groupBy = createAggregator(function(result, value, key) {
|
|
10027
|
-
if (hasOwnProperty$
|
|
9892
|
+
if (hasOwnProperty$2.call(result, key)) {
|
|
10028
9893
|
result[key].push(value);
|
|
10029
9894
|
} else {
|
|
10030
9895
|
baseAssignValue(result, key, [value]);
|
|
@@ -10241,7 +10106,7 @@ function baseOrderBy(collection, iteratees, orders) {
|
|
|
10241
10106
|
if (isArray(iteratee)) {
|
|
10242
10107
|
return function(value) {
|
|
10243
10108
|
return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
|
|
10244
|
-
}
|
|
10109
|
+
};
|
|
10245
10110
|
}
|
|
10246
10111
|
return iteratee;
|
|
10247
10112
|
});
|
|
@@ -10306,11 +10171,130 @@ var sortBy = baseRest(function(collection, iteratees) {
|
|
|
10306
10171
|
return baseOrderBy(collection, baseFlatten(iteratees), []);
|
|
10307
10172
|
});
|
|
10308
10173
|
|
|
10174
|
+
const pending = new Map();
|
|
10175
|
+
const inFlight = new Set();
|
|
10176
|
+
// Per-object view of `inFlight`, so a caller (notably `Model.destroy`) can
|
|
10177
|
+
// await the saves for a single object without blocking on unrelated writes.
|
|
10178
|
+
const inFlightByObj = new Map();
|
|
10179
|
+
let unloadListenerAttached = false;
|
|
10180
|
+
/**
|
|
10181
|
+
* Execute a save `run` now and track the resulting promise as in-flight until
|
|
10182
|
+
* it settles, both globally (`inFlight`) and per object (`inFlightByObj`), so
|
|
10183
|
+
* `flushPending({ wait: true })` can await every save and `Model.destroy` can
|
|
10184
|
+
* await just its own.
|
|
10185
|
+
*
|
|
10186
|
+
* @internal
|
|
10187
|
+
* @param obj - The owning model/collection (or `null` when the save isn't tied to one).
|
|
10188
|
+
* A rejection is logged and re-surfaced on `obj`'s `error` event.
|
|
10189
|
+
* Called when a debounce timer fires or a flush forces it.
|
|
10190
|
+
*/
|
|
10191
|
+
function fireRun(obj, run) {
|
|
10192
|
+
const p = Promise.resolve(run()).catch((e) => {
|
|
10193
|
+
console.error('Skeletor autoSync save error:', e);
|
|
10194
|
+
// Surface failures that bypassed `options.error` on the model's `error` event,
|
|
10195
|
+
// the same channel storage-layer failures already use. Storage saves route
|
|
10196
|
+
// errors through `options.error` and then resolve, so they never reach this
|
|
10197
|
+
// catch and won't double-emit.
|
|
10198
|
+
obj?.trigger?.('error', obj, e);
|
|
10199
|
+
});
|
|
10200
|
+
inFlight.add(p);
|
|
10201
|
+
let perObj;
|
|
10202
|
+
if (obj) {
|
|
10203
|
+
perObj = inFlightByObj.get(obj);
|
|
10204
|
+
if (!perObj) {
|
|
10205
|
+
perObj = new Set();
|
|
10206
|
+
inFlightByObj.set(obj, perObj);
|
|
10207
|
+
}
|
|
10208
|
+
perObj.add(p);
|
|
10209
|
+
}
|
|
10210
|
+
p.finally(() => {
|
|
10211
|
+
inFlight.delete(p);
|
|
10212
|
+
if (perObj) {
|
|
10213
|
+
perObj.delete(p);
|
|
10214
|
+
if (perObj.size === 0)
|
|
10215
|
+
inFlightByObj.delete(obj);
|
|
10216
|
+
}
|
|
10217
|
+
});
|
|
10218
|
+
}
|
|
10219
|
+
/**
|
|
10220
|
+
* Schedule a debounced auto-save for `obj`. Replaces any pending schedule
|
|
10221
|
+
* for the same object.
|
|
10222
|
+
* @internal
|
|
10223
|
+
*/
|
|
10224
|
+
function scheduleAutoSave(obj, run, delay) {
|
|
10225
|
+
const existing = pending.get(obj);
|
|
10226
|
+
if (existing)
|
|
10227
|
+
clearTimeout(existing.timerId);
|
|
10228
|
+
const timerId = setTimeout(() => {
|
|
10229
|
+
pending.delete(obj);
|
|
10230
|
+
fireRun(obj, run);
|
|
10231
|
+
}, delay);
|
|
10232
|
+
pending.set(obj, { timerId, run });
|
|
10233
|
+
}
|
|
10234
|
+
/**
|
|
10235
|
+
* Cancel any pending auto-save for `obj`.
|
|
10236
|
+
*
|
|
10237
|
+
* This only stops a *pending* (not-yet-fired) debounce timer. A save whose
|
|
10238
|
+
* timer has already fired is in flight and beyond cancellation — sequence
|
|
10239
|
+
* against it with {@link awaitInFlightSaves} instead.
|
|
10240
|
+
* @internal
|
|
10241
|
+
*/
|
|
10242
|
+
function cancelAutoSave(obj) {
|
|
10243
|
+
const existing = pending.get(obj);
|
|
10244
|
+
if (existing) {
|
|
10245
|
+
clearTimeout(existing.timerId);
|
|
10246
|
+
pending.delete(obj);
|
|
10247
|
+
}
|
|
10248
|
+
}
|
|
10249
|
+
/**
|
|
10250
|
+
* Return a promise that settles once every in-flight auto-save for `obj` has
|
|
10251
|
+
* completed, or `null` when none are in flight. `Model.destroy` uses this to
|
|
10252
|
+
* sequence its delete after a save that has already fired, so a late write
|
|
10253
|
+
* cannot land after the delete and resurrect the record.
|
|
10254
|
+
* @internal
|
|
10255
|
+
*/
|
|
10256
|
+
function awaitInFlightSaves(obj) {
|
|
10257
|
+
const set = inFlightByObj.get(obj);
|
|
10258
|
+
if (!set || set.size === 0)
|
|
10259
|
+
return null;
|
|
10260
|
+
return Promise.all([...set]).then(() => undefined);
|
|
10261
|
+
}
|
|
10262
|
+
function flushPending({ storage, wait = false, } = {}) {
|
|
10263
|
+
for (const [obj, { timerId, run }] of pending.entries()) {
|
|
10264
|
+
clearTimeout(timerId);
|
|
10265
|
+
fireRun(obj, run);
|
|
10266
|
+
}
|
|
10267
|
+
pending.clear();
|
|
10268
|
+
if (storage)
|
|
10269
|
+
storage.flushAll();
|
|
10270
|
+
if (wait)
|
|
10271
|
+
return Promise.all([...inFlight]).then(() => undefined);
|
|
10272
|
+
}
|
|
10273
|
+
/**
|
|
10274
|
+
* Lazily attach pagehide/visibilitychange listeners in browser environments
|
|
10275
|
+
* to flush pending writes when the page is hidden/unloading. This is a
|
|
10276
|
+
* best-effort durability measure: the flush initiates writes synchronously but
|
|
10277
|
+
* cannot guarantee an asynchronous backend finishes persisting them before the
|
|
10278
|
+
* page goes away. Called at most once.
|
|
10279
|
+
* @internal
|
|
10280
|
+
*/
|
|
10281
|
+
function ensureUnloadListener(storage) {
|
|
10282
|
+
if (unloadListenerAttached || typeof window === 'undefined')
|
|
10283
|
+
return;
|
|
10284
|
+
unloadListenerAttached = true;
|
|
10285
|
+
const flush = () => flushPending({ storage });
|
|
10286
|
+
window.addEventListener('pagehide', flush);
|
|
10287
|
+
window.addEventListener('visibilitychange', () => {
|
|
10288
|
+
if (document.visibilityState === 'hidden')
|
|
10289
|
+
flush();
|
|
10290
|
+
});
|
|
10291
|
+
}
|
|
10292
|
+
|
|
10309
10293
|
/** Used for built-in method references. */
|
|
10310
|
-
var objectProto$
|
|
10294
|
+
var objectProto$2 = Object.prototype;
|
|
10311
10295
|
|
|
10312
10296
|
/** Used to check objects for own properties. */
|
|
10313
|
-
var hasOwnProperty = objectProto$
|
|
10297
|
+
var hasOwnProperty$1 = objectProto$2.hasOwnProperty;
|
|
10314
10298
|
|
|
10315
10299
|
/**
|
|
10316
10300
|
* Assigns own and inherited enumerable string keyed properties of source
|
|
@@ -10355,7 +10339,7 @@ var defaults = baseRest(function(object, sources) {
|
|
|
10355
10339
|
var value = object[key];
|
|
10356
10340
|
|
|
10357
10341
|
if (value === undefined ||
|
|
10358
|
-
(eq(value, objectProto$
|
|
10342
|
+
(eq(value, objectProto$2[key]) && !hasOwnProperty$1.call(object, key))) {
|
|
10359
10343
|
object[key] = source[key];
|
|
10360
10344
|
}
|
|
10361
10345
|
}
|
|
@@ -10439,14 +10423,14 @@ function createInverter(setter, toIteratee) {
|
|
|
10439
10423
|
}
|
|
10440
10424
|
|
|
10441
10425
|
/** Used for built-in method references. */
|
|
10442
|
-
var objectProto = Object.prototype;
|
|
10426
|
+
var objectProto$1 = Object.prototype;
|
|
10443
10427
|
|
|
10444
10428
|
/**
|
|
10445
10429
|
* Used to resolve the
|
|
10446
10430
|
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
|
10447
10431
|
* of values.
|
|
10448
10432
|
*/
|
|
10449
|
-
var nativeObjectToString = objectProto.toString;
|
|
10433
|
+
var nativeObjectToString = objectProto$1.toString;
|
|
10450
10434
|
|
|
10451
10435
|
/**
|
|
10452
10436
|
* Creates an object composed of the inverted keys and values of `object`.
|
|
@@ -10617,6 +10601,12 @@ function parent(object, path) {
|
|
|
10617
10601
|
return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
|
|
10618
10602
|
}
|
|
10619
10603
|
|
|
10604
|
+
/** Used for built-in method references. */
|
|
10605
|
+
var objectProto = Object.prototype;
|
|
10606
|
+
|
|
10607
|
+
/** Used to check objects for own properties. */
|
|
10608
|
+
var hasOwnProperty = objectProto.hasOwnProperty;
|
|
10609
|
+
|
|
10620
10610
|
/**
|
|
10621
10611
|
* The base implementation of `_.unset`.
|
|
10622
10612
|
*
|
|
@@ -10627,8 +10617,34 @@ function parent(object, path) {
|
|
|
10627
10617
|
*/
|
|
10628
10618
|
function baseUnset(object, path) {
|
|
10629
10619
|
path = castPath(path, object);
|
|
10630
|
-
|
|
10631
|
-
|
|
10620
|
+
|
|
10621
|
+
// Prevent prototype pollution:
|
|
10622
|
+
// https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg
|
|
10623
|
+
// https://github.com/lodash/lodash/security/advisories/GHSA-f23m-r3pf-42rh
|
|
10624
|
+
var index = -1,
|
|
10625
|
+
length = path.length;
|
|
10626
|
+
|
|
10627
|
+
if (!length) {
|
|
10628
|
+
return true;
|
|
10629
|
+
}
|
|
10630
|
+
|
|
10631
|
+
while (++index < length) {
|
|
10632
|
+
var key = toKey(path[index]);
|
|
10633
|
+
|
|
10634
|
+
// Always block "__proto__" anywhere in the path if it's not expected
|
|
10635
|
+
if (key === '__proto__' && !hasOwnProperty.call(object, '__proto__')) {
|
|
10636
|
+
return false;
|
|
10637
|
+
}
|
|
10638
|
+
|
|
10639
|
+
// Block constructor/prototype as non-terminal traversal keys to prevent
|
|
10640
|
+
// escaping the object graph into built-in constructors and prototypes.
|
|
10641
|
+
if ((key === 'constructor' || key === 'prototype') && index < length - 1) {
|
|
10642
|
+
return false;
|
|
10643
|
+
}
|
|
10644
|
+
}
|
|
10645
|
+
|
|
10646
|
+
var obj = parent(object, path);
|
|
10647
|
+
return obj == null || delete obj[toKey(last(path))];
|
|
10632
10648
|
}
|
|
10633
10649
|
|
|
10634
10650
|
/**
|
|
@@ -10826,6 +10842,7 @@ var pick = flatRest(function(object, paths) {
|
|
|
10826
10842
|
return object == null ? {} : basePick(object, paths);
|
|
10827
10843
|
});
|
|
10828
10844
|
|
|
10845
|
+
var _Model_instances, _Model_computedCache, _Model_computedDefs, _Model_state, _Model_hydrate, _Model_doAutoSave, _Model_updateComputed, _Model_initComputed;
|
|
10829
10846
|
/**
|
|
10830
10847
|
* @public
|
|
10831
10848
|
* **Models** are the basic data object in the framework --
|
|
@@ -10840,6 +10857,10 @@ class Model extends EventEmitterObject {
|
|
|
10840
10857
|
*/
|
|
10841
10858
|
constructor(attributes, options) {
|
|
10842
10859
|
super();
|
|
10860
|
+
_Model_instances.add(this);
|
|
10861
|
+
_Model_computedCache.set(this, void 0);
|
|
10862
|
+
_Model_computedDefs.set(this, void 0);
|
|
10863
|
+
_Model_state.set(this, 'constructing');
|
|
10843
10864
|
this._changing = false;
|
|
10844
10865
|
this._pending = false;
|
|
10845
10866
|
this._url = '';
|
|
@@ -10857,15 +10878,74 @@ class Model extends EventEmitterObject {
|
|
|
10857
10878
|
const default_attrs = result(this, 'defaults');
|
|
10858
10879
|
attrs = defaults(Object.assign({}, default_attrs, attrs), default_attrs);
|
|
10859
10880
|
this.set(attrs, options);
|
|
10881
|
+
__classPrivateFieldGet(this, _Model_instances, "m", _Model_initComputed).call(this);
|
|
10882
|
+
this.attrs = new Proxy(this.attributes, {
|
|
10883
|
+
get: (_target, key) => {
|
|
10884
|
+
if (typeof key !== 'symbol' && __classPrivateFieldGet(this, _Model_computedCache, "f") && key in __classPrivateFieldGet(this, _Model_computedCache, "f")) {
|
|
10885
|
+
return __classPrivateFieldGet(this, _Model_computedCache, "f")[key];
|
|
10886
|
+
}
|
|
10887
|
+
return this.attributes[key];
|
|
10888
|
+
},
|
|
10889
|
+
set: (_target, key, value) => {
|
|
10890
|
+
this.set(key, value);
|
|
10891
|
+
return true;
|
|
10892
|
+
},
|
|
10893
|
+
});
|
|
10860
10894
|
this.initialize.apply(this, arguments);
|
|
10861
10895
|
// Reset changed after initial set
|
|
10862
10896
|
this.changed = {};
|
|
10897
|
+
// When autoSync is on, `initialized` is always a Promise so callers can
|
|
10898
|
+
// uniformly `await model.initialized`. It only hydrates from storage when
|
|
10899
|
+
// there's something to load (storage configured and the model isn't new);
|
|
10900
|
+
// otherwise it's already ready and resolves immediately.
|
|
10901
|
+
if (this.autoSync) {
|
|
10902
|
+
if (getStorage(this) && !this.isNew()) {
|
|
10903
|
+
__classPrivateFieldSet(this, _Model_state, 'hydrating', "f");
|
|
10904
|
+
this.initialized = __classPrivateFieldGet(this, _Model_instances, "m", _Model_hydrate).call(this);
|
|
10905
|
+
}
|
|
10906
|
+
else {
|
|
10907
|
+
__classPrivateFieldSet(this, _Model_state, 'ready', "f");
|
|
10908
|
+
this.initialized = Promise.resolve();
|
|
10909
|
+
}
|
|
10910
|
+
}
|
|
10911
|
+
else {
|
|
10912
|
+
__classPrivateFieldSet(this, _Model_state, 'ready', "f");
|
|
10913
|
+
}
|
|
10914
|
+
}
|
|
10915
|
+
/**
|
|
10916
|
+
* The canonical storage accessor. Set to a `PersistentStorage` instance
|
|
10917
|
+
* to enable local persistence for this model.
|
|
10918
|
+
*/
|
|
10919
|
+
get storage() {
|
|
10920
|
+
return this._storage;
|
|
10863
10921
|
}
|
|
10864
|
-
set
|
|
10865
|
-
this.
|
|
10922
|
+
set storage(s) {
|
|
10923
|
+
this._storage = s;
|
|
10924
|
+
PersistentStorage.register(s);
|
|
10866
10925
|
}
|
|
10926
|
+
/**
|
|
10927
|
+
* @deprecated Use `storage` instead.
|
|
10928
|
+
*/
|
|
10867
10929
|
get browserStorage() {
|
|
10868
|
-
return this.
|
|
10930
|
+
return this._storage;
|
|
10931
|
+
}
|
|
10932
|
+
set browserStorage(s) {
|
|
10933
|
+
warnBrowserStorageDeprecation(this);
|
|
10934
|
+
this.storage = s;
|
|
10935
|
+
}
|
|
10936
|
+
/**
|
|
10937
|
+
* Override to enable automatic persistence. When true, any `set()` call
|
|
10938
|
+
* that changes attributes will schedule a debounced save to `storage`, and
|
|
10939
|
+
* the model will auto-hydrate from storage on construction.
|
|
10940
|
+
*/
|
|
10941
|
+
get autoSync() {
|
|
10942
|
+
return false;
|
|
10943
|
+
}
|
|
10944
|
+
/**
|
|
10945
|
+
* Debounce delay (ms) for auto-save writes. Override to tune.
|
|
10946
|
+
*/
|
|
10947
|
+
get autoSyncDelay() {
|
|
10948
|
+
return 100;
|
|
10869
10949
|
}
|
|
10870
10950
|
/**
|
|
10871
10951
|
* The default name for the JSON `id` attribute is `"id"`. MongoDB and
|
|
@@ -10901,6 +10981,17 @@ class Model extends EventEmitterObject {
|
|
|
10901
10981
|
defaults() {
|
|
10902
10982
|
return {};
|
|
10903
10983
|
}
|
|
10984
|
+
/**
|
|
10985
|
+
* Declare computed properties. Override in subclasses to define properties
|
|
10986
|
+
* that derive their value from other attributes. Each entry specifies the
|
|
10987
|
+
* attribute keys it depends on (`deps`) and a function (`fn`) that receives
|
|
10988
|
+
* the model and returns the computed value. The value is cached and
|
|
10989
|
+
* recalculated automatically when any dep changes, firing a `change:key`
|
|
10990
|
+
* event.
|
|
10991
|
+
*/
|
|
10992
|
+
get computed() {
|
|
10993
|
+
return {};
|
|
10994
|
+
}
|
|
10904
10995
|
/**
|
|
10905
10996
|
* Return a copy of the model's `attributes` object.
|
|
10906
10997
|
*/
|
|
@@ -10914,9 +11005,12 @@ class Model extends EventEmitterObject {
|
|
|
10914
11005
|
return getSyncMethod(model)(method, model, options);
|
|
10915
11006
|
}
|
|
10916
11007
|
/**
|
|
10917
|
-
* Get the value of an attribute.
|
|
11008
|
+
* Get the value of an attribute, or a computed property.
|
|
10918
11009
|
*/
|
|
10919
11010
|
get(attr) {
|
|
11011
|
+
if (__classPrivateFieldGet(this, _Model_computedCache, "f") && attr in __classPrivateFieldGet(this, _Model_computedCache, "f")) {
|
|
11012
|
+
return __classPrivateFieldGet(this, _Model_computedCache, "f")[attr];
|
|
11013
|
+
}
|
|
10920
11014
|
return this.attributes[attr];
|
|
10921
11015
|
}
|
|
10922
11016
|
keys() {
|
|
@@ -10981,6 +11075,11 @@ class Model extends EventEmitterObject {
|
|
|
10981
11075
|
attrs[key] = val;
|
|
10982
11076
|
}
|
|
10983
11077
|
options = options || {};
|
|
11078
|
+
// Guard must come after arg normalization: when called as set(obj, opts),
|
|
11079
|
+
// fromStorage lives in `val` (second arg), not `options` (third arg).
|
|
11080
|
+
if (this.autoSync && __classPrivateFieldGet(this, _Model_state, "f") === 'hydrating' && !options.fromStorage) {
|
|
11081
|
+
throw new Error(`Skeletor: set() called on an autoSync model before initialized resolved. Await model.initialized first.`);
|
|
11082
|
+
}
|
|
10984
11083
|
// Run validation.
|
|
10985
11084
|
if (!this._validate(attrs, options))
|
|
10986
11085
|
return null;
|
|
@@ -11021,6 +11120,14 @@ class Model extends EventEmitterObject {
|
|
|
11021
11120
|
this.trigger('change:' + changes[i], this, current[changes[i]], options);
|
|
11022
11121
|
}
|
|
11023
11122
|
}
|
|
11123
|
+
// Recalculate computed properties whose deps changed.
|
|
11124
|
+
if (changes.length && __classPrivateFieldGet(this, _Model_computedDefs, "f")) {
|
|
11125
|
+
for (const [key, def] of Object.entries(__classPrivateFieldGet(this, _Model_computedDefs, "f"))) {
|
|
11126
|
+
if (def.deps.some((dep) => changes.includes(dep))) {
|
|
11127
|
+
__classPrivateFieldGet(this, _Model_instances, "m", _Model_updateComputed).call(this, key, def, silent, options);
|
|
11128
|
+
}
|
|
11129
|
+
}
|
|
11130
|
+
}
|
|
11024
11131
|
if (changing)
|
|
11025
11132
|
return this;
|
|
11026
11133
|
if (!silent) {
|
|
@@ -11034,6 +11141,17 @@ class Model extends EventEmitterObject {
|
|
|
11034
11141
|
}
|
|
11035
11142
|
this._pending = false;
|
|
11036
11143
|
this._changing = false;
|
|
11144
|
+
// Auto-save: schedule a debounced write when autoSync is on and there
|
|
11145
|
+
// were actual changes that originated from application code (not a
|
|
11146
|
+
// storage read or an explicit noAutoSave call).
|
|
11147
|
+
if (__classPrivateFieldGet(this, _Model_state, "f") === 'ready' &&
|
|
11148
|
+
this.autoSync &&
|
|
11149
|
+
getStorage(this) &&
|
|
11150
|
+
changes.length &&
|
|
11151
|
+
!options.fromStorage &&
|
|
11152
|
+
!options.noAutoSave) {
|
|
11153
|
+
scheduleAutoSave(this, () => __classPrivateFieldGet(this, _Model_instances, "m", _Model_doAutoSave).call(this), this.autoSyncDelay);
|
|
11154
|
+
}
|
|
11037
11155
|
return this;
|
|
11038
11156
|
}
|
|
11039
11157
|
/**
|
|
@@ -11108,16 +11226,48 @@ class Model extends EventEmitterObject {
|
|
|
11108
11226
|
fetch(options = {}) {
|
|
11109
11227
|
options = Object.assign({ parse: true }, options);
|
|
11110
11228
|
const success = options.success;
|
|
11229
|
+
const promise = options.promise ? getResolveablePromise() : undefined;
|
|
11230
|
+
// Tracks whether sync invoked one of the callbacks. A sync may instead
|
|
11231
|
+
// settle its returned promise; the `.then`/`.catch` below bridges that to
|
|
11232
|
+
// the callbacks so the fetch promise never hangs. The flag is set
|
|
11233
|
+
// synchronously inside each callback (before sync's promise resolves), so
|
|
11234
|
+
// it's reliable by the time those handlers run.
|
|
11235
|
+
let settled = false;
|
|
11111
11236
|
options.success = (resp) => {
|
|
11237
|
+
settled = true;
|
|
11112
11238
|
const serverAttrs = options.parse ? this.parse(resp, options) : resp;
|
|
11113
|
-
|
|
11239
|
+
// fromStorage prevents the set() from triggering auto-save on reads
|
|
11240
|
+
if (!this.set(serverAttrs, Object.assign({}, options, { fromStorage: true })))
|
|
11114
11241
|
return false;
|
|
11115
11242
|
if (success)
|
|
11116
11243
|
success.call(options.context, this, resp, options);
|
|
11117
11244
|
this.trigger('sync', this, resp, options);
|
|
11245
|
+
promise && promise.resolve(resp);
|
|
11118
11246
|
};
|
|
11119
|
-
wrapError(this, options);
|
|
11120
|
-
|
|
11247
|
+
wrapError(this, options, promise);
|
|
11248
|
+
if (promise) {
|
|
11249
|
+
const onError = options.error;
|
|
11250
|
+
options.error = (resp) => {
|
|
11251
|
+
settled = true;
|
|
11252
|
+
onError(resp);
|
|
11253
|
+
};
|
|
11254
|
+
}
|
|
11255
|
+
const result = this.sync('read', this, options);
|
|
11256
|
+
if (promise) {
|
|
11257
|
+
Promise.resolve(result).then(
|
|
11258
|
+
// A sync that resolves its promise without invoking options.success:
|
|
11259
|
+
// treat the resolved value as the response, so the model is still
|
|
11260
|
+
// merged and the promise settles instead of hanging.
|
|
11261
|
+
(value) => {
|
|
11262
|
+
if (!settled)
|
|
11263
|
+
options.success(value);
|
|
11264
|
+
},
|
|
11265
|
+
// A sync that rejects instead of invoking options.error; settling
|
|
11266
|
+
// twice is a harmless no-op.
|
|
11267
|
+
(e) => promise.reject(e));
|
|
11268
|
+
return promise;
|
|
11269
|
+
}
|
|
11270
|
+
return result;
|
|
11121
11271
|
}
|
|
11122
11272
|
/**
|
|
11123
11273
|
* Set a hash of model attributes, and sync the model to the server.
|
|
@@ -11194,6 +11344,7 @@ class Model extends EventEmitterObject {
|
|
|
11194
11344
|
* If `wait: true` is passed, waits for the server to respond before removal.
|
|
11195
11345
|
*/
|
|
11196
11346
|
destroy(options) {
|
|
11347
|
+
cancelAutoSave(this);
|
|
11197
11348
|
options = options ? clone(options) : {};
|
|
11198
11349
|
const success = options.success;
|
|
11199
11350
|
const wait = options.wait;
|
|
@@ -11209,13 +11360,25 @@ class Model extends EventEmitterObject {
|
|
|
11209
11360
|
if (!this.isNew())
|
|
11210
11361
|
this.trigger('sync', this, resp, options);
|
|
11211
11362
|
};
|
|
11363
|
+
// A debounced auto-save may already have fired and be in flight.
|
|
11364
|
+
// cancelAutoSave() above only stops a *pending* timer, so sequence the
|
|
11365
|
+
// delete after any in-flight save; otherwise the late write could land
|
|
11366
|
+
// after the delete and resurrect the record. Capture the collection now,
|
|
11367
|
+
// the optimistic in-memory removal below nulls `model.collection` before
|
|
11368
|
+
// the deferred sync runs, but the storage layer still needs it to drop
|
|
11369
|
+
// this id from the collection's persisted index.
|
|
11370
|
+
const inFlightSave = awaitInFlightSaves(this);
|
|
11371
|
+
if (inFlightSave && this.collection)
|
|
11372
|
+
options.collection = this.collection;
|
|
11212
11373
|
let xhr = false;
|
|
11213
11374
|
if (this.isNew()) {
|
|
11214
11375
|
defer(options.success);
|
|
11215
11376
|
}
|
|
11216
11377
|
else {
|
|
11217
11378
|
wrapError(this, options);
|
|
11218
|
-
xhr =
|
|
11379
|
+
xhr = inFlightSave
|
|
11380
|
+
? inFlightSave.then(() => this.sync('delete', this, options))
|
|
11381
|
+
: this.sync('delete', this, options);
|
|
11219
11382
|
}
|
|
11220
11383
|
if (!wait)
|
|
11221
11384
|
destroy();
|
|
@@ -11263,6 +11426,14 @@ class Model extends EventEmitterObject {
|
|
|
11263
11426
|
isValid(options) {
|
|
11264
11427
|
return this._validate({}, Object.assign({}, options, { validate: true }));
|
|
11265
11428
|
}
|
|
11429
|
+
subscribe(eventOrCallback, callback, context) {
|
|
11430
|
+
if (typeof eventOrCallback === 'function') {
|
|
11431
|
+
const cb = (model) => eventOrCallback(model, this.changed);
|
|
11432
|
+
this.on('change', cb);
|
|
11433
|
+
return () => this.off('change', cb);
|
|
11434
|
+
}
|
|
11435
|
+
return super.subscribe(eventOrCallback, callback, context);
|
|
11436
|
+
}
|
|
11266
11437
|
/**
|
|
11267
11438
|
* Run validation against the next complete set of model attributes,
|
|
11268
11439
|
* returning `true` if all is well. Otherwise, fire an `"invalid"` event.
|
|
@@ -11278,8 +11449,43 @@ class Model extends EventEmitterObject {
|
|
|
11278
11449
|
return false;
|
|
11279
11450
|
}
|
|
11280
11451
|
}
|
|
11452
|
+
_Model_computedCache = new WeakMap(), _Model_computedDefs = new WeakMap(), _Model_state = new WeakMap(), _Model_instances = new WeakSet(), _Model_hydrate = async function _Model_hydrate() {
|
|
11453
|
+
ensureUnloadListener(PersistentStorage);
|
|
11454
|
+
try {
|
|
11455
|
+
await this.fetch({ fromStorage: true, promise: true });
|
|
11456
|
+
}
|
|
11457
|
+
catch (e) {
|
|
11458
|
+
// 'Record Not Found' is a normal first-run state (nothing stored yet);
|
|
11459
|
+
// keep the initial attributes and resolve. Re-throw anything else.
|
|
11460
|
+
if (e !== 'Record Not Found')
|
|
11461
|
+
throw e;
|
|
11462
|
+
}
|
|
11463
|
+
finally {
|
|
11464
|
+
__classPrivateFieldSet(this, _Model_state, 'ready', "f");
|
|
11465
|
+
}
|
|
11466
|
+
}, _Model_doAutoSave = function _Model_doAutoSave() {
|
|
11467
|
+
return this.save(null, { noAutoSave: true });
|
|
11468
|
+
}, _Model_updateComputed = function _Model_updateComputed(key, def, silent, options) {
|
|
11469
|
+
const newVal = def.fn(this);
|
|
11470
|
+
if (!isEqual(__classPrivateFieldGet(this, _Model_computedCache, "f")[key], newVal)) {
|
|
11471
|
+
__classPrivateFieldGet(this, _Model_computedCache, "f")[key] = newVal;
|
|
11472
|
+
if (!silent) {
|
|
11473
|
+
this.changed[key] = newVal;
|
|
11474
|
+
this.trigger('change:' + key, this, newVal, options);
|
|
11475
|
+
}
|
|
11476
|
+
}
|
|
11477
|
+
}, _Model_initComputed = function _Model_initComputed() {
|
|
11478
|
+
const defs = result(this, 'computed');
|
|
11479
|
+
if (!defs || isEmpty(defs))
|
|
11480
|
+
return;
|
|
11481
|
+
__classPrivateFieldSet(this, _Model_computedDefs, defs, "f");
|
|
11482
|
+
__classPrivateFieldSet(this, _Model_computedCache, {}, "f");
|
|
11483
|
+
for (const [key, def] of Object.entries(defs)) {
|
|
11484
|
+
__classPrivateFieldGet(this, _Model_computedCache, "f")[key] = def.fn(this);
|
|
11485
|
+
}
|
|
11486
|
+
};
|
|
11281
11487
|
|
|
11282
|
-
var _a;
|
|
11488
|
+
var _Collection_instances, _Collection_hydrate, _a;
|
|
11283
11489
|
// Default options for `Collection#set`.
|
|
11284
11490
|
const setOptions = { add: true, remove: true, merge: true };
|
|
11285
11491
|
const addOptions = { add: true, remove: false };
|
|
@@ -11300,6 +11506,7 @@ class Collection extends EventEmitterObject {
|
|
|
11300
11506
|
*/
|
|
11301
11507
|
constructor(models, options) {
|
|
11302
11508
|
super();
|
|
11509
|
+
_Collection_instances.add(this);
|
|
11303
11510
|
this._url = '';
|
|
11304
11511
|
/**
|
|
11305
11512
|
* @public
|
|
@@ -11317,6 +11524,12 @@ class Collection extends EventEmitterObject {
|
|
|
11317
11524
|
if (models)
|
|
11318
11525
|
this.reset(models, Object.assign({ silent: true }, options));
|
|
11319
11526
|
this[Symbol.iterator] = this.values;
|
|
11527
|
+
// When autoSync is on, `initialized` is always a Promise so callers can
|
|
11528
|
+
// uniformly `await collection.initialized`; it resolves immediately when
|
|
11529
|
+
// there's no storage to hydrate from.
|
|
11530
|
+
if (this.autoSync) {
|
|
11531
|
+
this.initialized = getStorage(this) ? __classPrivateFieldGet(this, _Collection_instances, "m", _Collection_hydrate).call(this) : Promise.resolve();
|
|
11532
|
+
}
|
|
11320
11533
|
}
|
|
11321
11534
|
get comparator() {
|
|
11322
11535
|
return this._comparator;
|
|
@@ -11324,11 +11537,40 @@ class Collection extends EventEmitterObject {
|
|
|
11324
11537
|
set comparator(c) {
|
|
11325
11538
|
this._comparator = c;
|
|
11326
11539
|
}
|
|
11327
|
-
|
|
11328
|
-
|
|
11540
|
+
/**
|
|
11541
|
+
* The canonical storage accessor. Set to a `PersistentStorage` instance
|
|
11542
|
+
* to enable local persistence for this collection.
|
|
11543
|
+
*/
|
|
11544
|
+
get storage() {
|
|
11545
|
+
return this._storage;
|
|
11546
|
+
}
|
|
11547
|
+
set storage(s) {
|
|
11548
|
+
this._storage = s;
|
|
11549
|
+
PersistentStorage.register(s);
|
|
11329
11550
|
}
|
|
11551
|
+
/**
|
|
11552
|
+
* @deprecated Use `storage` instead.
|
|
11553
|
+
*/
|
|
11330
11554
|
get browserStorage() {
|
|
11331
|
-
return this.
|
|
11555
|
+
return this._storage;
|
|
11556
|
+
}
|
|
11557
|
+
set browserStorage(s) {
|
|
11558
|
+
warnBrowserStorageDeprecation(this);
|
|
11559
|
+
this.storage = s;
|
|
11560
|
+
}
|
|
11561
|
+
/**
|
|
11562
|
+
* Override to return `true` to automatically load the collection from
|
|
11563
|
+
* storage on construction. Await `initialized` to know when hydration
|
|
11564
|
+
* is complete.
|
|
11565
|
+
*
|
|
11566
|
+
* Note: collection `autoSync` is hydrate-only. Unlike `Model`, it does
|
|
11567
|
+
* **not** schedule auto-saves when the collection changes (`add`/`remove`/
|
|
11568
|
+
* `reset`). Persisting members is each model's responsibility — enable
|
|
11569
|
+
* `autoSync` on the contained model class and every model writes its own
|
|
11570
|
+
* record. A collection-level write would be redundant with that.
|
|
11571
|
+
*/
|
|
11572
|
+
get autoSync() {
|
|
11573
|
+
return false;
|
|
11332
11574
|
}
|
|
11333
11575
|
/**
|
|
11334
11576
|
* The default model for a collection is just a **Model**.
|
|
@@ -11523,7 +11765,7 @@ class Collection extends EventEmitterObject {
|
|
|
11523
11765
|
}));
|
|
11524
11766
|
});
|
|
11525
11767
|
}));
|
|
11526
|
-
await this
|
|
11768
|
+
await getStorage(this)?.clear();
|
|
11527
11769
|
this.reset();
|
|
11528
11770
|
}
|
|
11529
11771
|
/**
|
|
@@ -11761,17 +12003,47 @@ class Collection extends EventEmitterObject {
|
|
|
11761
12003
|
const success = options.success;
|
|
11762
12004
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
11763
12005
|
const collection = this;
|
|
11764
|
-
const promise = options.promise
|
|
12006
|
+
const promise = options.promise ? getResolveablePromise() : undefined;
|
|
12007
|
+
// Tracks whether sync invoked one of the callbacks. A sync may instead
|
|
12008
|
+
// settle its returned promise; the `.then`/`.catch` below bridges that to
|
|
12009
|
+
// the callbacks so the fetch promise never hangs. The flag is set
|
|
12010
|
+
// synchronously inside each callback (before sync's promise resolves), so
|
|
12011
|
+
// it's reliable by the time those handlers run.
|
|
12012
|
+
let settled = false;
|
|
11765
12013
|
options.success = function (resp) {
|
|
12014
|
+
settled = true;
|
|
11766
12015
|
const method = options.reset ? 'reset' : 'set';
|
|
11767
|
-
|
|
12016
|
+
// fromStorage prevents individual model set() calls from triggering auto-save on reads
|
|
12017
|
+
collection[method](resp, Object.assign({}, options, { fromStorage: true }));
|
|
11768
12018
|
if (success)
|
|
11769
12019
|
success.call(options.context, collection, resp, options);
|
|
11770
12020
|
promise && promise.resolve();
|
|
11771
12021
|
collection.trigger('sync', collection, resp, options);
|
|
11772
12022
|
};
|
|
11773
|
-
wrapError(this, options);
|
|
11774
|
-
|
|
12023
|
+
wrapError(this, options, promise);
|
|
12024
|
+
if (promise) {
|
|
12025
|
+
const onError = options.error;
|
|
12026
|
+
options.error = (resp) => {
|
|
12027
|
+
settled = true;
|
|
12028
|
+
onError(resp);
|
|
12029
|
+
};
|
|
12030
|
+
}
|
|
12031
|
+
const result = this.sync('read', this, options);
|
|
12032
|
+
if (promise) {
|
|
12033
|
+
Promise.resolve(result).then(
|
|
12034
|
+
// A sync that resolves its promise without invoking options.success:
|
|
12035
|
+
// treat the resolved value as the response, so the collection is still
|
|
12036
|
+
// populated and the promise settles instead of hanging.
|
|
12037
|
+
(value) => {
|
|
12038
|
+
if (!settled)
|
|
12039
|
+
options.success(value);
|
|
12040
|
+
},
|
|
12041
|
+
// A sync that rejects instead of invoking options.error; settling
|
|
12042
|
+
// twice is a harmless no-op.
|
|
12043
|
+
(e) => promise.reject(e));
|
|
12044
|
+
return promise;
|
|
12045
|
+
}
|
|
12046
|
+
return result;
|
|
11775
12047
|
}
|
|
11776
12048
|
/**
|
|
11777
12049
|
* Create a new instance of a model in this collection. Add the model to the
|
|
@@ -11815,6 +12087,14 @@ class Collection extends EventEmitterObject {
|
|
|
11815
12087
|
return preparedModel;
|
|
11816
12088
|
}
|
|
11817
12089
|
}
|
|
12090
|
+
subscribe(eventOrCallback, callback, context) {
|
|
12091
|
+
if (typeof eventOrCallback === 'function') {
|
|
12092
|
+
const cb = () => eventOrCallback(this);
|
|
12093
|
+
this.on('update reset sort', cb);
|
|
12094
|
+
return () => this.off('update reset sort', cb);
|
|
12095
|
+
}
|
|
12096
|
+
return super.subscribe(eventOrCallback, callback, context);
|
|
12097
|
+
}
|
|
11818
12098
|
/**
|
|
11819
12099
|
* **parse** converts a response into a list of models to be added to the
|
|
11820
12100
|
* collection. The default implementation is just to pass it through.
|
|
@@ -11952,7 +12232,12 @@ class Collection extends EventEmitterObject {
|
|
|
11952
12232
|
this.trigger.apply(this, arguments);
|
|
11953
12233
|
}
|
|
11954
12234
|
}
|
|
11955
|
-
|
|
12235
|
+
_Collection_instances = new WeakSet(), _Collection_hydrate = async function _Collection_hydrate() {
|
|
12236
|
+
ensureUnloadListener(PersistentStorage);
|
|
12237
|
+
// findAll() returns [] for an empty store, so a first-run collection
|
|
12238
|
+
// resolves rather than erroring the way a model fetch-by-id would.
|
|
12239
|
+
await this.fetch({ fromStorage: true, promise: true });
|
|
12240
|
+
}, _a = Symbol.iterator;
|
|
11956
12241
|
// This "enum" defines the three possible kinds of values which can be emitted
|
|
11957
12242
|
// by a CollectionIterator that correspond to the values(), keys() and entries()
|
|
11958
12243
|
// methods on Collection, respectively.
|
|
@@ -12041,6 +12326,11 @@ function noConflict() {
|
|
|
12041
12326
|
}
|
|
12042
12327
|
skeletor.noConflict = noConflict;
|
|
12043
12328
|
root.Skeletor = skeletor;
|
|
12329
|
+
/**
|
|
12330
|
+
* @deprecated Use `PersistentStorage` instead.
|
|
12331
|
+
* @public
|
|
12332
|
+
*/
|
|
12333
|
+
const BrowserStorage = PersistentStorage;
|
|
12044
12334
|
|
|
12045
|
-
export { BrowserStorage, Collection, EventEmitter, Model, skeletor as default, noConflict, sync };
|
|
12335
|
+
export { BrowserStorage, Collection, EventEmitter, Model, PersistentStorage, skeletor as default, getStorage, noConflict, sync };
|
|
12046
12336
|
//# sourceMappingURL=skeletor.esm.js.map
|