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