react-native-onyx 1.0.119 → 1.0.121
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 +7 -0
- package/dist/web.development.js +408 -113
- package/dist/web.development.js.map +1 -1
- package/dist/web.min.js +1 -1
- package/dist/web.min.js.map +1 -1
- package/lib/ActiveClientManager/index.d.ts +22 -0
- package/lib/ActiveClientManager/index.native.js +23 -0
- package/lib/ActiveClientManager/index.web.js +99 -0
- package/lib/Logger.js +1 -5
- package/lib/MDTable.js +11 -14
- package/lib/Onyx.d.ts +11 -4
- package/lib/Onyx.js +344 -232
- package/lib/OnyxCache.js +12 -3
- package/lib/Str.js +17 -4
- package/lib/broadcast/index.d.ts +17 -0
- package/lib/broadcast/index.native.js +14 -0
- package/lib/broadcast/index.web.js +35 -0
- package/lib/compose.js +6 -2
- package/lib/metrics/PerformanceUtils.js +2 -7
- package/lib/metrics/index.native.js +28 -41
- package/lib/metrics/index.web.js +4 -7
- package/lib/storage/WebStorage.js +6 -11
- package/lib/storage/__mocks__/index.js +2 -2
- package/lib/storage/providers/IDBKeyVal.js +27 -37
- package/lib/storage/providers/SQLiteStorage.js +58 -62
- package/lib/types.d.ts +1 -13
- package/lib/utils.d.ts +2 -6
- package/lib/utils.js +19 -22
- package/lib/withOnyx.d.ts +8 -32
- package/lib/withOnyx.js +37 -34
- package/package.json +15 -6
package/lib/OnyxCache.js
CHANGED
|
@@ -43,8 +43,17 @@ class OnyxCache {
|
|
|
43
43
|
// bind all public methods to prevent problems with `this`
|
|
44
44
|
_.bindAll(
|
|
45
45
|
this,
|
|
46
|
-
'getAllKeys',
|
|
47
|
-
'
|
|
46
|
+
'getAllKeys',
|
|
47
|
+
'getValue',
|
|
48
|
+
'hasCacheForKey',
|
|
49
|
+
'addKey',
|
|
50
|
+
'set',
|
|
51
|
+
'drop',
|
|
52
|
+
'merge',
|
|
53
|
+
'hasPendingTask',
|
|
54
|
+
'getTaskPromise',
|
|
55
|
+
'captureTask',
|
|
56
|
+
'removeLeastRecentlyUsedKeys',
|
|
48
57
|
'setRecentKeysLimit',
|
|
49
58
|
);
|
|
50
59
|
}
|
|
@@ -126,7 +135,7 @@ class OnyxCache {
|
|
|
126
135
|
const storageKeys = this.getAllKeys();
|
|
127
136
|
const mergedKeys = _.keys(data);
|
|
128
137
|
this.storageKeys = new Set([...storageKeys, ...mergedKeys]);
|
|
129
|
-
_.each(mergedKeys, key => this.addToAccessedKeys(key));
|
|
138
|
+
_.each(mergedKeys, (key) => this.addToAccessedKeys(key));
|
|
130
139
|
}
|
|
131
140
|
|
|
132
141
|
/**
|
package/lib/Str.js
CHANGED
|
@@ -8,9 +8,7 @@ import _ from 'underscore';
|
|
|
8
8
|
* @return {Boolean} Returns true if the haystack starts with the needle.
|
|
9
9
|
*/
|
|
10
10
|
function startsWith(haystack, needle) {
|
|
11
|
-
return _.isString(haystack)
|
|
12
|
-
&& _.isString(needle)
|
|
13
|
-
&& haystack.startsWith(needle);
|
|
11
|
+
return _.isString(haystack) && _.isString(needle) && haystack.startsWith(needle);
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
/**
|
|
@@ -26,4 +24,19 @@ function result(parameter, ...args) {
|
|
|
26
24
|
return _.isFunction(parameter) ? parameter(...args) : parameter;
|
|
27
25
|
}
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
/**
|
|
28
|
+
* A simple GUID generator taken from https://stackoverflow.com/a/32760401/9114791
|
|
29
|
+
*
|
|
30
|
+
* @param {String} [prefix] an optional prefix to put in front of the guid
|
|
31
|
+
* @returns {String}
|
|
32
|
+
*/
|
|
33
|
+
function guid(prefix = '') {
|
|
34
|
+
function s4() {
|
|
35
|
+
return Math.floor((1 + Math.random()) * 0x10000)
|
|
36
|
+
.toString(16)
|
|
37
|
+
.substring(1);
|
|
38
|
+
}
|
|
39
|
+
return `${prefix}${s4()}${s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export {guid, startsWith, result};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sends a message to the broadcast channel.
|
|
3
|
+
*/
|
|
4
|
+
declare function sendMessage(message: string): void;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Subscribes to the broadcast channel. Every time a new message
|
|
8
|
+
* is received, the callback is called.
|
|
9
|
+
*/
|
|
10
|
+
declare function subscribe(callback: () => {}): void;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Disconnects from the broadcast channel.
|
|
14
|
+
*/
|
|
15
|
+
declare function disconnect(): void;
|
|
16
|
+
|
|
17
|
+
export {sendMessage, subscribe, disconnect};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* For native devices, there will never be more than one
|
|
3
|
+
* client running at a time, so this lib is a big no-op
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
function sendMessage() {}
|
|
7
|
+
|
|
8
|
+
function subscribe() {}
|
|
9
|
+
|
|
10
|
+
function disconnect() {}
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
sendMessage, subscribe, disconnect,
|
|
14
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const BROADCAST_ONYX = 'BROADCAST_ONYX';
|
|
2
|
+
|
|
3
|
+
const subscriptions = [];
|
|
4
|
+
const channel = new BroadcastChannel(BROADCAST_ONYX);
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Sends a message to the broadcast channel.
|
|
8
|
+
* @param {String} message
|
|
9
|
+
*/
|
|
10
|
+
function sendMessage(message) {
|
|
11
|
+
channel.postMessage(message);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Subscribes to the broadcast channel. Every time a new message
|
|
16
|
+
* is received, the callback is called.
|
|
17
|
+
* @param {Function} callback
|
|
18
|
+
*/
|
|
19
|
+
function subscribe(callback) {
|
|
20
|
+
subscriptions.push(callback);
|
|
21
|
+
channel.onmessage = (message) => {
|
|
22
|
+
subscriptions.forEach(c => c(message));
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Disconnects from the broadcast channel.
|
|
28
|
+
*/
|
|
29
|
+
function disconnect() {
|
|
30
|
+
channel.close();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
sendMessage, subscribe, disconnect,
|
|
35
|
+
};
|
package/lib/compose.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
export default function compose(...funcs) {
|
|
20
20
|
if (funcs.length === 0) {
|
|
21
|
-
return arg => arg;
|
|
21
|
+
return (arg) => arg;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
if (funcs.length === 1) {
|
|
@@ -26,5 +26,9 @@ export default function compose(...funcs) {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// eslint-disable-next-line rulesdir/prefer-underscore-method
|
|
29
|
-
return funcs.reduce(
|
|
29
|
+
return funcs.reduce(
|
|
30
|
+
(a, b) =>
|
|
31
|
+
(...args) =>
|
|
32
|
+
a(b(...args)),
|
|
33
|
+
);
|
|
30
34
|
}
|
|
@@ -26,9 +26,7 @@ function diffObject(object, base) {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// eslint-disable-next-line no-param-reassign
|
|
29
|
-
result[key] =
|
|
30
|
-
? changes(value, comparisonObject[key])
|
|
31
|
-
: value;
|
|
29
|
+
result[key] = _.isObject(value) && _.isObject(comparisonObject[key]) ? changes(value, comparisonObject[key]) : value;
|
|
32
30
|
});
|
|
33
31
|
}
|
|
34
32
|
return changes(object, base);
|
|
@@ -62,7 +60,4 @@ function logSetStateCall(mapping, previousValue, newValue, caller, keyThatChange
|
|
|
62
60
|
console.debug(`[Onyx-Debug] ${mapping.displayName} setState() called. Subscribed to key '${mapping.key}' (${caller})`, logParams);
|
|
63
61
|
}
|
|
64
62
|
|
|
65
|
-
export {
|
|
66
|
-
logSetStateCall,
|
|
67
|
-
setShouldDebugSetState,
|
|
68
|
-
};
|
|
63
|
+
export {logSetStateCall, setShouldDebugSetState};
|
|
@@ -47,9 +47,9 @@ function decorateWithMetrics(func, alias = func.name) {
|
|
|
47
47
|
const originalPromise = func.apply(this, args);
|
|
48
48
|
|
|
49
49
|
/*
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
* Then handlers added here are not affecting the original promise
|
|
51
|
+
* They create a separate chain that's not exposed (returned) to the original caller
|
|
52
|
+
* */
|
|
53
53
|
originalPromise
|
|
54
54
|
.then((result) => {
|
|
55
55
|
measureMarkToNow(mark, {result});
|
|
@@ -84,26 +84,29 @@ function sum(list, prop) {
|
|
|
84
84
|
*/
|
|
85
85
|
function getMetrics() {
|
|
86
86
|
const summaries = _.chain(performance.getEntriesByType('measure'))
|
|
87
|
-
.filter(entry => entry.detail && decoratedAliases.has(entry.detail.alias))
|
|
88
|
-
.groupBy(entry => entry.detail.alias)
|
|
87
|
+
.filter((entry) => entry.detail && decoratedAliases.has(entry.detail.alias))
|
|
88
|
+
.groupBy((entry) => entry.detail.alias)
|
|
89
89
|
.map((calls, methodName) => {
|
|
90
90
|
const total = sum(calls, 'duration');
|
|
91
|
-
const avg =
|
|
91
|
+
const avg = total / calls.length || 0;
|
|
92
92
|
const max = _.max(calls, 'duration').duration || 0;
|
|
93
93
|
const min = _.min(calls, 'duration').duration || 0;
|
|
94
94
|
|
|
95
95
|
// Latest complete call (by end time) for all the calls made to the current method
|
|
96
|
-
const lastCall = _.max(calls, call => call.startTime + call.duration);
|
|
96
|
+
const lastCall = _.max(calls, (call) => call.startTime + call.duration);
|
|
97
97
|
|
|
98
|
-
return [
|
|
98
|
+
return [
|
|
99
99
|
methodName,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
{
|
|
101
|
+
methodName,
|
|
102
|
+
total,
|
|
103
|
+
max,
|
|
104
|
+
min,
|
|
105
|
+
avg,
|
|
106
|
+
lastCall,
|
|
107
|
+
calls,
|
|
108
|
+
},
|
|
109
|
+
];
|
|
107
110
|
})
|
|
108
111
|
.object() // Create a map like methodName -> StatSummary
|
|
109
112
|
.value();
|
|
@@ -111,10 +114,7 @@ function getMetrics() {
|
|
|
111
114
|
const totalTime = sum(_.values(summaries), 'total');
|
|
112
115
|
|
|
113
116
|
// Latest complete call (by end time) of all methods up to this point
|
|
114
|
-
const lastCompleteCall = _.max(
|
|
115
|
-
_.values(summaries),
|
|
116
|
-
summary => summary.lastCall.startTime + summary.lastCall.duration,
|
|
117
|
-
).lastCall;
|
|
117
|
+
const lastCompleteCall = _.max(_.values(summaries), (summary) => summary.lastCall.startTime + summary.lastCall.duration).lastCall;
|
|
118
118
|
|
|
119
119
|
return {
|
|
120
120
|
totalTime,
|
|
@@ -177,7 +177,7 @@ function printMetrics({raw = false, format = 'console', methods} = {}) {
|
|
|
177
177
|
const methodNames = _.isArray(methods) ? methods : _.keys(summaries);
|
|
178
178
|
|
|
179
179
|
const methodCallTables = _.chain(methodNames)
|
|
180
|
-
.filter(methodName => summaries[methodName] && summaries[methodName].avg > 0)
|
|
180
|
+
.filter((methodName) => summaries[methodName] && summaries[methodName].avg > 0)
|
|
181
181
|
.map((methodName) => {
|
|
182
182
|
const {calls, ...methodStats} = summaries[methodName];
|
|
183
183
|
tableSummary.addRow(
|
|
@@ -186,7 +186,7 @@ function printMetrics({raw = false, format = 'console', methods} = {}) {
|
|
|
186
186
|
toDuration(methodStats.max, raw),
|
|
187
187
|
toDuration(methodStats.min, raw),
|
|
188
188
|
toDuration(methodStats.avg, raw),
|
|
189
|
-
toDuration(
|
|
189
|
+
toDuration(methodStats.lastCall.startTime + methodStats.lastCall.duration - timeOrigin, raw),
|
|
190
190
|
calls.length,
|
|
191
191
|
);
|
|
192
192
|
|
|
@@ -194,12 +194,12 @@ function printMetrics({raw = false, format = 'console', methods} = {}) {
|
|
|
194
194
|
title: methodName,
|
|
195
195
|
heading: ['start time', 'end time', 'duration', 'args'],
|
|
196
196
|
leftAlignedCols: [3],
|
|
197
|
-
rows: _.map(calls, call =>
|
|
197
|
+
rows: _.map(calls, (call) => [
|
|
198
198
|
toDuration(call.startTime - performance.timeOrigin, raw),
|
|
199
|
-
toDuration(
|
|
199
|
+
toDuration(call.startTime + call.duration - timeOrigin, raw),
|
|
200
200
|
toDuration(call.duration, raw),
|
|
201
201
|
_.map(call.detail.args, String).join(', ').slice(0, 60), // Restrict cell width to 60 chars max
|
|
202
|
-
])
|
|
202
|
+
]),
|
|
203
203
|
});
|
|
204
204
|
})
|
|
205
205
|
.value();
|
|
@@ -219,17 +219,9 @@ function printMetrics({raw = false, format = 'console', methods} = {}) {
|
|
|
219
219
|
}).join('\n\n');
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
const lastComplete = lastCompleteCall && toDuration(
|
|
223
|
-
(lastCompleteCall.startTime + lastCompleteCall.duration) - timeOrigin, raw,
|
|
224
|
-
);
|
|
222
|
+
const lastComplete = lastCompleteCall && toDuration(lastCompleteCall.startTime + lastCompleteCall.duration - timeOrigin, raw);
|
|
225
223
|
|
|
226
|
-
const mainOutput = [
|
|
227
|
-
'### Onyx Benchmark',
|
|
228
|
-
` - Total: ${toDuration(totalTime, raw)}`,
|
|
229
|
-
` - Last call finished at: ${lastComplete || 'N/A'}`,
|
|
230
|
-
'',
|
|
231
|
-
tableSummary.toString(),
|
|
232
|
-
];
|
|
224
|
+
const mainOutput = ['### Onyx Benchmark', ` - Total: ${toDuration(totalTime, raw)}`, ` - Last call finished at: ${lastComplete || 'N/A'}`, '', tableSummary.toString()];
|
|
233
225
|
|
|
234
226
|
/* eslint-disable no-console */
|
|
235
227
|
console.info(mainOutput.join('\n'));
|
|
@@ -248,7 +240,7 @@ function resetMetrics() {
|
|
|
248
240
|
const {summaries} = getMetrics();
|
|
249
241
|
|
|
250
242
|
_.chain(summaries)
|
|
251
|
-
.map(summary => summary.calls)
|
|
243
|
+
.map((summary) => summary.calls)
|
|
252
244
|
.flatten()
|
|
253
245
|
.each((measure) => {
|
|
254
246
|
performance.clearMarks(measure.detail.alias);
|
|
@@ -256,9 +248,4 @@ function resetMetrics() {
|
|
|
256
248
|
});
|
|
257
249
|
}
|
|
258
250
|
|
|
259
|
-
export {
|
|
260
|
-
decorateWithMetrics,
|
|
261
|
-
getMetrics,
|
|
262
|
-
resetMetrics,
|
|
263
|
-
printMetrics,
|
|
264
|
-
};
|
|
251
|
+
export {decorateWithMetrics, getMetrics, resetMetrics, printMetrics};
|
package/lib/metrics/index.web.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
// For web-only implementations of Onyx, this module will just be a no-op
|
|
2
2
|
|
|
3
|
-
function decorateWithMetrics(func) {
|
|
3
|
+
function decorateWithMetrics(func) {
|
|
4
|
+
return func;
|
|
5
|
+
}
|
|
4
6
|
function getMetrics() {}
|
|
5
7
|
function printMetrics() {}
|
|
6
8
|
function resetMetrics() {}
|
|
7
9
|
|
|
8
|
-
export {
|
|
9
|
-
decorateWithMetrics,
|
|
10
|
-
getMetrics,
|
|
11
|
-
resetMetrics,
|
|
12
|
-
printMetrics,
|
|
13
|
-
};
|
|
10
|
+
export {decorateWithMetrics, getMetrics, resetMetrics, printMetrics};
|
|
@@ -31,17 +31,13 @@ const webStorage = {
|
|
|
31
31
|
*/
|
|
32
32
|
keepInstancesSync(onStorageKeyChanged) {
|
|
33
33
|
// Override set, remove and clear to raise storage events that we intercept in other tabs
|
|
34
|
-
this.setItem = (key, value) => Storage.setItem(key, value)
|
|
35
|
-
.then(() => raiseStorageSyncEvent(key));
|
|
34
|
+
this.setItem = (key, value) => Storage.setItem(key, value).then(() => raiseStorageSyncEvent(key));
|
|
36
35
|
|
|
37
|
-
this.removeItem = key => Storage.removeItem(key)
|
|
38
|
-
.then(() => raiseStorageSyncEvent(key));
|
|
36
|
+
this.removeItem = (key) => Storage.removeItem(key).then(() => raiseStorageSyncEvent(key));
|
|
39
37
|
|
|
40
|
-
this.removeItems = keys => Storage.removeItems(keys)
|
|
41
|
-
.then(() => raiseStorageSyncManyKeysEvent(keys));
|
|
38
|
+
this.removeItems = (keys) => Storage.removeItems(keys).then(() => raiseStorageSyncManyKeysEvent(keys));
|
|
42
39
|
|
|
43
|
-
this.mergeItem = (key, batchedChanges, modifiedData) => Storage.mergeItem(key, batchedChanges, modifiedData)
|
|
44
|
-
.then(() => raiseStorageSyncEvent(key));
|
|
40
|
+
this.mergeItem = (key, batchedChanges, modifiedData) => Storage.mergeItem(key, batchedChanges, modifiedData).then(() => raiseStorageSyncEvent(key));
|
|
45
41
|
|
|
46
42
|
// If we just call Storage.clear other tabs will have no idea which keys were available previously
|
|
47
43
|
// so that they can call keysChanged for them. That's why we iterate over every key and raise a storage sync
|
|
@@ -49,7 +45,7 @@ const webStorage = {
|
|
|
49
45
|
this.clear = () => {
|
|
50
46
|
let allKeys;
|
|
51
47
|
|
|
52
|
-
//
|
|
48
|
+
// The keys must be retrieved before storage is cleared or else the list of keys would be empty
|
|
53
49
|
return Storage.getAllKeys()
|
|
54
50
|
.then((keys) => {
|
|
55
51
|
allKeys = keys;
|
|
@@ -70,8 +66,7 @@ const webStorage = {
|
|
|
70
66
|
}
|
|
71
67
|
|
|
72
68
|
const onyxKey = event.newValue;
|
|
73
|
-
Storage.getItem(onyxKey)
|
|
74
|
-
.then(value => onStorageKeyChanged(onyxKey, value));
|
|
69
|
+
Storage.getItem(onyxKey).then((value) => onStorageKeyChanged(onyxKey, value));
|
|
75
70
|
});
|
|
76
71
|
},
|
|
77
72
|
};
|
|
@@ -14,13 +14,13 @@ const idbKeyvalMock = {
|
|
|
14
14
|
},
|
|
15
15
|
multiSet(pairs) {
|
|
16
16
|
const setPromises = _.map(pairs, ([key, value]) => this.setItem(key, value));
|
|
17
|
-
return new Promise(resolve => Promise.all(setPromises).then(() => resolve(storageMapInternal)));
|
|
17
|
+
return new Promise((resolve) => Promise.all(setPromises).then(() => resolve(storageMapInternal)));
|
|
18
18
|
},
|
|
19
19
|
getItem(key) {
|
|
20
20
|
return Promise.resolve(storageMapInternal[key]);
|
|
21
21
|
},
|
|
22
22
|
multiGet(keys) {
|
|
23
|
-
const getPromises = _.map(keys, key => new Promise(resolve => this.getItem(key).then(value => resolve([key, value]))));
|
|
23
|
+
const getPromises = _.map(keys, (key) => new Promise((resolve) => this.getItem(key).then((value) => resolve([key, value]))));
|
|
24
24
|
return Promise.all(getPromises);
|
|
25
25
|
},
|
|
26
26
|
multiMerge(pairs) {
|
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
set,
|
|
3
|
-
keys,
|
|
4
|
-
getMany,
|
|
5
|
-
setMany,
|
|
6
|
-
get,
|
|
7
|
-
clear,
|
|
8
|
-
del,
|
|
9
|
-
delMany,
|
|
10
|
-
createStore,
|
|
11
|
-
promisifyRequest,
|
|
12
|
-
} from 'idb-keyval';
|
|
1
|
+
import {set, keys, getMany, setMany, get, clear, del, delMany, createStore, promisifyRequest} from 'idb-keyval';
|
|
13
2
|
import _ from 'underscore';
|
|
14
3
|
import utils from '../../utils';
|
|
15
4
|
|
|
@@ -38,8 +27,7 @@ const provider = {
|
|
|
38
27
|
* @param {String[]} keysParam
|
|
39
28
|
* @return {Promise<Array<[key, value]>>}
|
|
40
29
|
*/
|
|
41
|
-
multiGet: keysParam => getMany(keysParam, getCustomStore())
|
|
42
|
-
.then(values => _.map(values, (value, index) => [keysParam[index], value])),
|
|
30
|
+
multiGet: (keysParam) => getMany(keysParam, getCustomStore()).then((values) => _.map(values, (value, index) => [keysParam[index], value])),
|
|
43
31
|
|
|
44
32
|
/**
|
|
45
33
|
* Multiple merging of existing and new values in a batch
|
|
@@ -47,21 +35,22 @@ const provider = {
|
|
|
47
35
|
* This function also removes all nested null values from an object.
|
|
48
36
|
* @return {Promise<void>}
|
|
49
37
|
*/
|
|
50
|
-
multiMerge: pairs
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
38
|
+
multiMerge: (pairs) =>
|
|
39
|
+
getCustomStore()('readwrite', (store) => {
|
|
40
|
+
// Note: we are using the manual store transaction here, to fit the read and update
|
|
41
|
+
// of the items in one transaction to achieve best performance.
|
|
42
|
+
|
|
43
|
+
const getValues = Promise.all(_.map(pairs, ([key]) => promisifyRequest(store.get(key))));
|
|
44
|
+
|
|
45
|
+
return getValues.then((values) => {
|
|
46
|
+
const upsertMany = _.map(pairs, ([key, value], index) => {
|
|
47
|
+
const prev = values[index];
|
|
48
|
+
const newValue = utils.fastMerge(prev, value);
|
|
49
|
+
return promisifyRequest(store.put(newValue, key));
|
|
50
|
+
});
|
|
51
|
+
return Promise.all(upsertMany);
|
|
61
52
|
});
|
|
62
|
-
|
|
63
|
-
});
|
|
64
|
-
}),
|
|
53
|
+
}),
|
|
65
54
|
|
|
66
55
|
/**
|
|
67
56
|
* Merging an existing value with a new one
|
|
@@ -80,7 +69,7 @@ const provider = {
|
|
|
80
69
|
* @param {Array<[key, value]>} pairs
|
|
81
70
|
* @return {Promise<void>}
|
|
82
71
|
*/
|
|
83
|
-
multiSet: pairs => setMany(pairs, getCustomStore()),
|
|
72
|
+
multiSet: (pairs) => setMany(pairs, getCustomStore()),
|
|
84
73
|
|
|
85
74
|
/**
|
|
86
75
|
* Clear everything from storage and also stops the SyncQueue from adding anything more to storage
|
|
@@ -102,17 +91,17 @@ const provider = {
|
|
|
102
91
|
* @param {String} key
|
|
103
92
|
* @return {Promise<*>}
|
|
104
93
|
*/
|
|
105
|
-
getItem: key =>
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
94
|
+
getItem: (key) =>
|
|
95
|
+
get(key, getCustomStore())
|
|
96
|
+
// idb-keyval returns undefined for missing items, but this needs to return null so that idb-keyval does the same thing as SQLiteStorage.
|
|
97
|
+
.then((val) => (val === undefined ? null : val)),
|
|
109
98
|
|
|
110
99
|
/**
|
|
111
100
|
* Remove given key and it's value from storage
|
|
112
101
|
* @param {String} key
|
|
113
102
|
* @returns {Promise<void>}
|
|
114
103
|
*/
|
|
115
|
-
removeItem: key => del(key, getCustomStore()),
|
|
104
|
+
removeItem: (key) => del(key, getCustomStore()),
|
|
116
105
|
|
|
117
106
|
/**
|
|
118
107
|
* Remove given keys and their values from storage
|
|
@@ -120,7 +109,7 @@ const provider = {
|
|
|
120
109
|
* @param {Array} keysParam
|
|
121
110
|
* @returns {Promise}
|
|
122
111
|
*/
|
|
123
|
-
removeItems: keysParam => delMany(keysParam, getCustomStore()),
|
|
112
|
+
removeItems: (keysParam) => delMany(keysParam, getCustomStore()),
|
|
124
113
|
|
|
125
114
|
/**
|
|
126
115
|
* Gets the total bytes of the database file
|
|
@@ -131,8 +120,9 @@ const provider = {
|
|
|
131
120
|
throw new Error('StorageManager browser API unavailable');
|
|
132
121
|
}
|
|
133
122
|
|
|
134
|
-
return window.navigator.storage
|
|
135
|
-
.
|
|
123
|
+
return window.navigator.storage
|
|
124
|
+
.estimate()
|
|
125
|
+
.then((value) => ({
|
|
136
126
|
bytesUsed: value.usage,
|
|
137
127
|
bytesRemaining: value.quota - value.usage,
|
|
138
128
|
}))
|