react-native-onyx 1.0.131 → 2.0.2
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/API.md +83 -22
- package/README.md +3 -5
- package/dist/DevTools.d.ts +23 -0
- package/{lib → dist}/DevTools.js +16 -18
- package/dist/Logger.js +32 -0
- package/dist/MDTable.d.ts +36 -0
- package/{lib → dist}/MDTable.js +12 -17
- package/{lib → dist}/Onyx.js +278 -477
- package/dist/OnyxCache.d.ts +121 -0
- package/{lib → dist}/OnyxCache.js +16 -53
- package/{lib/Str.js → dist/Str.d.ts} +2 -11
- package/dist/Str.js +31 -0
- package/dist/SyncQueue.d.ts +32 -0
- package/{lib → dist}/SyncQueue.js +9 -11
- package/dist/batch.d.ts +2 -0
- package/dist/batch.js +4 -0
- package/dist/batch.native.d.ts +2 -0
- package/dist/batch.native.js +4 -0
- package/dist/compose.d.ts +19 -0
- package/{lib → dist}/compose.js +5 -8
- package/dist/createDeferredTask.d.ts +12 -0
- package/{lib → dist}/createDeferredTask.js +4 -2
- package/dist/index.d.ts +6 -0
- package/dist/index.js +10 -0
- package/dist/metrics/PerformanceUtils.d.ts +14 -0
- package/{lib → dist}/metrics/PerformanceUtils.js +16 -16
- package/dist/metrics/index.d.ts +4 -0
- package/dist/metrics/index.js +14 -0
- package/dist/metrics/index.native.d.ts +43 -0
- package/{lib → dist}/metrics/index.native.js +80 -102
- package/{lib/storage/NativeStorage.js → dist/storage/NativeStorage.d.ts} +1 -2
- package/dist/storage/NativeStorage.js +7 -0
- package/dist/storage/WebStorage.d.ts +19 -0
- package/{lib → dist}/storage/WebStorage.js +24 -34
- package/dist/storage/__mocks__/index.d.ts +23 -0
- package/{lib → dist}/storage/__mocks__/index.js +17 -19
- package/{lib/storage/index.web.js → dist/storage/index.d.ts} +1 -2
- package/dist/storage/index.js +7 -0
- package/{lib/storage/index.native.js → dist/storage/index.native.d.ts} +1 -2
- package/dist/storage/index.native.js +7 -0
- package/dist/storage/providers/IDBKeyVal.d.ts +26 -0
- package/{lib → dist}/storage/providers/IDBKeyVal.js +38 -52
- package/dist/storage/providers/SQLiteStorage.d.ts +52 -0
- package/{lib → dist}/storage/providers/SQLiteStorage.js +27 -42
- package/{lib → dist}/utils.js +14 -27
- package/{lib → dist}/withOnyx.js +122 -159
- package/package.json +23 -54
- package/dist/web.development.js +0 -4308
- package/dist/web.development.js.map +0 -1
- package/dist/web.min.js +0 -2
- package/dist/web.min.js.map +0 -1
- package/lib/Logger.js +0 -31
- package/lib/batch.js +0 -3
- package/lib/batch.native.js +0 -3
- package/lib/index.d.ts +0 -6
- package/lib/index.js +0 -5
- package/lib/metrics/index.web.js +0 -10
- package/native.js +0 -11
- package/web.js +0 -12
- /package/{lib → dist}/Logger.d.ts +0 -0
- /package/{lib → dist}/Onyx.d.ts +0 -0
- /package/{lib → dist}/types.d.ts +0 -0
- /package/{lib → dist}/utils.d.ts +0 -0
- /package/{lib → dist}/withOnyx.d.ts +0 -0
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.setShouldDebugSetState = exports.logSetStateCall = void 0;
|
|
7
|
+
const transform_1 = __importDefault(require("lodash/transform"));
|
|
8
|
+
const underscore_1 = __importDefault(require("underscore"));
|
|
4
9
|
let debugSetState = false;
|
|
5
|
-
|
|
6
10
|
/**
|
|
7
11
|
* @param {Boolean} debug
|
|
8
12
|
*/
|
|
9
13
|
function setShouldDebugSetState(debug) {
|
|
10
14
|
debugSetState = debug;
|
|
11
15
|
}
|
|
12
|
-
|
|
16
|
+
exports.setShouldDebugSetState = setShouldDebugSetState;
|
|
13
17
|
/**
|
|
14
18
|
* Deep diff between two objects. Useful for figuring out what changed about an object from one render to the next so
|
|
15
19
|
* that state and props updates can be optimized.
|
|
@@ -20,18 +24,16 @@ function setShouldDebugSetState(debug) {
|
|
|
20
24
|
*/
|
|
21
25
|
function diffObject(object, base) {
|
|
22
26
|
function changes(obj, comparisonObject) {
|
|
23
|
-
return
|
|
24
|
-
if (
|
|
27
|
+
return (0, transform_1.default)(obj, (result, value, key) => {
|
|
28
|
+
if (underscore_1.default.isEqual(value, comparisonObject[key])) {
|
|
25
29
|
return;
|
|
26
30
|
}
|
|
27
|
-
|
|
28
31
|
// eslint-disable-next-line no-param-reassign
|
|
29
|
-
result[key] =
|
|
32
|
+
result[key] = underscore_1.default.isObject(value) && underscore_1.default.isObject(comparisonObject[key]) ? changes(value, comparisonObject[key]) : value;
|
|
30
33
|
});
|
|
31
34
|
}
|
|
32
35
|
return changes(object, base);
|
|
33
36
|
}
|
|
34
|
-
|
|
35
37
|
/**
|
|
36
38
|
* Provide insights into why a setState() call occurred by diffing the before and after values.
|
|
37
39
|
*
|
|
@@ -45,19 +47,17 @@ function logSetStateCall(mapping, previousValue, newValue, caller, keyThatChange
|
|
|
45
47
|
if (!debugSetState) {
|
|
46
48
|
return;
|
|
47
49
|
}
|
|
48
|
-
|
|
49
50
|
const logParams = {};
|
|
50
51
|
if (keyThatChanged) {
|
|
51
52
|
logParams.keyThatChanged = keyThatChanged;
|
|
52
53
|
}
|
|
53
|
-
if (
|
|
54
|
+
if (underscore_1.default.isObject(newValue) && underscore_1.default.isObject(previousValue)) {
|
|
54
55
|
logParams.difference = diffObject(previousValue, newValue);
|
|
55
|
-
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
56
58
|
logParams.previousValue = previousValue;
|
|
57
59
|
logParams.newValue = newValue;
|
|
58
60
|
}
|
|
59
|
-
|
|
60
61
|
console.debug(`[Onyx-Debug] ${mapping.displayName} setState() called. Subscribed to key '${mapping.key}' (${caller})`, logParams);
|
|
61
62
|
}
|
|
62
|
-
|
|
63
|
-
export {logSetStateCall, setShouldDebugSetState};
|
|
63
|
+
exports.logSetStateCall = logSetStateCall;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// For web-only implementations of Onyx, this module will just be a no-op
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.printMetrics = exports.resetMetrics = exports.getMetrics = exports.decorateWithMetrics = void 0;
|
|
5
|
+
function decorateWithMetrics(func) {
|
|
6
|
+
return func;
|
|
7
|
+
}
|
|
8
|
+
exports.decorateWithMetrics = decorateWithMetrics;
|
|
9
|
+
function getMetrics() { }
|
|
10
|
+
exports.getMetrics = getMetrics;
|
|
11
|
+
function printMetrics() { }
|
|
12
|
+
exports.printMetrics = printMetrics;
|
|
13
|
+
function resetMetrics() { }
|
|
14
|
+
exports.resetMetrics = resetMetrics;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wraps a function with metrics capturing logic
|
|
3
|
+
* @param {function} func
|
|
4
|
+
* @param {String} [alias]
|
|
5
|
+
* @returns {function} The wrapped function
|
|
6
|
+
*/
|
|
7
|
+
export function decorateWithMetrics(func: Function, alias?: string | undefined): Function;
|
|
8
|
+
/**
|
|
9
|
+
* Aggregates and returns benchmark information
|
|
10
|
+
* @returns {{summaries: Record<string, Object>, totalTime: number, lastCompleteCall: *}}
|
|
11
|
+
* An object with
|
|
12
|
+
* - `totalTime` - total time spent by decorated methods
|
|
13
|
+
* - `lastCompleteCall` - millisecond since launch the last call completed at
|
|
14
|
+
* - `summaries` - mapping of all captured stats: summaries.methodName -> method stats
|
|
15
|
+
*/
|
|
16
|
+
export function getMetrics(): {
|
|
17
|
+
summaries: Record<string, Object>;
|
|
18
|
+
totalTime: number;
|
|
19
|
+
lastCompleteCall: any;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Clears all collected metrics.
|
|
23
|
+
*/
|
|
24
|
+
export function resetMetrics(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Print extensive information on the dev console
|
|
27
|
+
* max, min, average, total time for each method
|
|
28
|
+
* and a table of individual calls
|
|
29
|
+
*
|
|
30
|
+
* @param {Object} [options]
|
|
31
|
+
* @param {boolean} [options.raw=false] - setting this to true will print raw instead of human friendly times
|
|
32
|
+
* Useful when you copy the printed table to excel and let excel do the number formatting
|
|
33
|
+
* @param {'console'|'csv'|'json'|'string'} [options.format=console] The output format of this function
|
|
34
|
+
* `string` is useful when __DEV__ is set to `false` as writing to the console is disabled, but the result of this
|
|
35
|
+
* method would still get printed as output
|
|
36
|
+
* @param {string[]} [options.methods] Print stats only for these method names
|
|
37
|
+
* @returns {string|undefined}
|
|
38
|
+
*/
|
|
39
|
+
export function printMetrics({ raw, format, methods }?: {
|
|
40
|
+
raw?: boolean | undefined;
|
|
41
|
+
format?: "string" | "console" | "csv" | "json" | undefined;
|
|
42
|
+
methods?: string[] | undefined;
|
|
43
|
+
} | undefined): string | undefined;
|
|
@@ -1,9 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.printMetrics = exports.resetMetrics = exports.getMetrics = exports.decorateWithMetrics = void 0;
|
|
18
|
+
const underscore_1 = __importDefault(require("underscore"));
|
|
19
|
+
const react_native_performance_1 = __importDefault(require("react-native-performance"));
|
|
20
|
+
const MDTable_1 = __importDefault(require("../MDTable"));
|
|
5
21
|
const decoratedAliases = new Set();
|
|
6
|
-
|
|
7
22
|
/**
|
|
8
23
|
* Capture a start mark to performance entries
|
|
9
24
|
* @param {string} alias
|
|
@@ -11,22 +26,20 @@ const decoratedAliases = new Set();
|
|
|
11
26
|
* @returns {{name: string, startTime:number, detail: {args: [], alias: string}}}
|
|
12
27
|
*/
|
|
13
28
|
function addMark(alias, args) {
|
|
14
|
-
return
|
|
29
|
+
return react_native_performance_1.default.mark(alias, { detail: { args, alias } });
|
|
15
30
|
}
|
|
16
|
-
|
|
17
31
|
/**
|
|
18
32
|
* Capture a measurement between the start mark and now
|
|
19
33
|
* @param {{name: string, startTime:number, detail: {args: []}}} startMark
|
|
20
34
|
* @param {*} detail
|
|
21
35
|
*/
|
|
22
36
|
function measureMarkToNow(startMark, detail) {
|
|
23
|
-
|
|
37
|
+
react_native_performance_1.default.measure(`${startMark.name} [${startMark.detail.args.toString()}]`, {
|
|
24
38
|
start: startMark.startTime,
|
|
25
|
-
end:
|
|
26
|
-
detail: {
|
|
39
|
+
end: react_native_performance_1.default.now(),
|
|
40
|
+
detail: Object.assign(Object.assign({}, startMark.detail), detail),
|
|
27
41
|
});
|
|
28
42
|
}
|
|
29
|
-
|
|
30
43
|
/**
|
|
31
44
|
* Wraps a function with metrics capturing logic
|
|
32
45
|
* @param {function} func
|
|
@@ -37,33 +50,27 @@ function decorateWithMetrics(func, alias = func.name) {
|
|
|
37
50
|
if (decoratedAliases.has(alias)) {
|
|
38
51
|
throw new Error(`"${alias}" is already decorated`);
|
|
39
52
|
}
|
|
40
|
-
|
|
41
53
|
decoratedAliases.add(alias);
|
|
42
|
-
|
|
43
54
|
function decorated(...args) {
|
|
44
55
|
const mark = addMark(alias, args);
|
|
45
|
-
|
|
46
56
|
// eslint-disable-next-line no-invalid-this
|
|
47
57
|
const originalPromise = func.apply(this, args);
|
|
48
|
-
|
|
49
58
|
/*
|
|
50
59
|
* Then handlers added here are not affecting the original promise
|
|
51
60
|
* They create a separate chain that's not exposed (returned) to the original caller
|
|
52
61
|
* */
|
|
53
62
|
originalPromise
|
|
54
63
|
.then((result) => {
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
measureMarkToNow(mark, { result });
|
|
65
|
+
})
|
|
57
66
|
.catch((error) => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
67
|
+
measureMarkToNow(mark, { error });
|
|
68
|
+
});
|
|
61
69
|
return originalPromise;
|
|
62
70
|
}
|
|
63
|
-
|
|
64
71
|
return decorated;
|
|
65
72
|
}
|
|
66
|
-
|
|
73
|
+
exports.decorateWithMetrics = decorateWithMetrics;
|
|
67
74
|
/**
|
|
68
75
|
* Calculate the total sum of a given key in a list
|
|
69
76
|
* @param {Array<Record<prop, Number>>} list
|
|
@@ -71,9 +78,8 @@ function decorateWithMetrics(func, alias = func.name) {
|
|
|
71
78
|
* @returns {number}
|
|
72
79
|
*/
|
|
73
80
|
function sum(list, prop) {
|
|
74
|
-
return
|
|
81
|
+
return underscore_1.default.reduce(list, (memo, next) => memo + next[prop], 0);
|
|
75
82
|
}
|
|
76
|
-
|
|
77
83
|
/**
|
|
78
84
|
* Aggregates and returns benchmark information
|
|
79
85
|
* @returns {{summaries: Record<string, Object>, totalTime: number, lastCompleteCall: *}}
|
|
@@ -83,46 +89,41 @@ function sum(list, prop) {
|
|
|
83
89
|
* - `summaries` - mapping of all captured stats: summaries.methodName -> method stats
|
|
84
90
|
*/
|
|
85
91
|
function getMetrics() {
|
|
86
|
-
const summaries =
|
|
92
|
+
const summaries = underscore_1.default.chain(react_native_performance_1.default.getEntriesByType('measure'))
|
|
87
93
|
.filter((entry) => entry.detail && decoratedAliases.has(entry.detail.alias))
|
|
88
94
|
.groupBy((entry) => entry.detail.alias)
|
|
89
95
|
.map((calls, methodName) => {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
const total = sum(calls, 'duration');
|
|
97
|
+
const avg = total / calls.length || 0;
|
|
98
|
+
const max = underscore_1.default.max(calls, 'duration').duration || 0;
|
|
99
|
+
const min = underscore_1.default.min(calls, 'duration').duration || 0;
|
|
100
|
+
// Latest complete call (by end time) for all the calls made to the current method
|
|
101
|
+
const lastCall = underscore_1.default.max(calls, (call) => call.startTime + call.duration);
|
|
102
|
+
return [
|
|
103
|
+
methodName,
|
|
104
|
+
{
|
|
99
105
|
methodName,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
];
|
|
110
|
-
})
|
|
106
|
+
total,
|
|
107
|
+
max,
|
|
108
|
+
min,
|
|
109
|
+
avg,
|
|
110
|
+
lastCall,
|
|
111
|
+
calls,
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
})
|
|
111
115
|
.object() // Create a map like methodName -> StatSummary
|
|
112
116
|
.value();
|
|
113
|
-
|
|
114
|
-
const totalTime = sum(_.values(summaries), 'total');
|
|
115
|
-
|
|
117
|
+
const totalTime = sum(underscore_1.default.values(summaries), 'total');
|
|
116
118
|
// Latest complete call (by end time) of all methods up to this point
|
|
117
|
-
const lastCompleteCall =
|
|
118
|
-
|
|
119
|
+
const lastCompleteCall = underscore_1.default.max(underscore_1.default.values(summaries), (summary) => summary.lastCall.startTime + summary.lastCall.duration).lastCall;
|
|
119
120
|
return {
|
|
120
121
|
totalTime,
|
|
121
122
|
summaries,
|
|
122
123
|
lastCompleteCall,
|
|
123
124
|
};
|
|
124
125
|
}
|
|
125
|
-
|
|
126
|
+
exports.getMetrics = getMetrics;
|
|
126
127
|
/**
|
|
127
128
|
* Convert milliseconds to human readable time
|
|
128
129
|
* @param {number} millis
|
|
@@ -133,20 +134,16 @@ function toDuration(millis, raw = false) {
|
|
|
133
134
|
if (raw) {
|
|
134
135
|
return millis;
|
|
135
136
|
}
|
|
136
|
-
|
|
137
137
|
const minute = 60 * 1000;
|
|
138
138
|
if (millis > minute) {
|
|
139
139
|
return `${(millis / minute).toFixed(1)}min`;
|
|
140
140
|
}
|
|
141
|
-
|
|
142
141
|
const second = 1000;
|
|
143
142
|
if (millis > second) {
|
|
144
143
|
return `${(millis / second).toFixed(2)}sec`;
|
|
145
144
|
}
|
|
146
|
-
|
|
147
145
|
return `${millis.toFixed(3)}ms`;
|
|
148
146
|
}
|
|
149
|
-
|
|
150
147
|
/**
|
|
151
148
|
* Print extensive information on the dev console
|
|
152
149
|
* max, min, average, total time for each method
|
|
@@ -161,53 +158,39 @@ function toDuration(millis, raw = false) {
|
|
|
161
158
|
* @param {string[]} [options.methods] Print stats only for these method names
|
|
162
159
|
* @returns {string|undefined}
|
|
163
160
|
*/
|
|
164
|
-
function printMetrics({raw = false, format = 'console', methods} = {}) {
|
|
165
|
-
const {totalTime, summaries, lastCompleteCall} = getMetrics();
|
|
166
|
-
|
|
167
|
-
const tableSummary = MDTable.factory({
|
|
161
|
+
function printMetrics({ raw = false, format = 'console', methods } = {}) {
|
|
162
|
+
const { totalTime, summaries, lastCompleteCall } = getMetrics();
|
|
163
|
+
const tableSummary = MDTable_1.default.factory({
|
|
168
164
|
heading: ['method', 'total time spent', 'max', 'min', 'avg', 'time last call completed', 'calls made'],
|
|
169
165
|
leftAlignedCols: [0],
|
|
170
166
|
});
|
|
171
|
-
|
|
172
167
|
/* Performance marks (startTimes) are relative to system uptime
|
|
173
168
|
* timeOrigin is the point at which the app started to init
|
|
174
169
|
* We use timeOrigin to display times relative to app launch time
|
|
175
170
|
* See: https://github.com/oblador/react-native-performance/issues/50 */
|
|
176
|
-
const timeOrigin =
|
|
177
|
-
const methodNames =
|
|
178
|
-
|
|
179
|
-
const methodCallTables = _.chain(methodNames)
|
|
171
|
+
const timeOrigin = react_native_performance_1.default.timeOrigin;
|
|
172
|
+
const methodNames = underscore_1.default.isArray(methods) ? methods : underscore_1.default.keys(summaries);
|
|
173
|
+
const methodCallTables = underscore_1.default.chain(methodNames)
|
|
180
174
|
.filter((methodName) => summaries[methodName] && summaries[methodName].avg > 0)
|
|
181
175
|
.map((methodName) => {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
toDuration(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
leftAlignedCols: [3],
|
|
197
|
-
rows: _.map(calls, (call) => [
|
|
198
|
-
toDuration(call.startTime - performance.timeOrigin, raw),
|
|
199
|
-
toDuration(call.startTime + call.duration - timeOrigin, raw),
|
|
200
|
-
toDuration(call.duration, raw),
|
|
201
|
-
_.map(call.detail.args, String).join(', ').slice(0, 60), // Restrict cell width to 60 chars max
|
|
202
|
-
]),
|
|
203
|
-
});
|
|
204
|
-
})
|
|
176
|
+
const _a = summaries[methodName], { calls } = _a, methodStats = __rest(_a, ["calls"]);
|
|
177
|
+
tableSummary.addRow(methodName, toDuration(methodStats.total, raw), toDuration(methodStats.max, raw), toDuration(methodStats.min, raw), toDuration(methodStats.avg, raw), toDuration(methodStats.lastCall.startTime + methodStats.lastCall.duration - timeOrigin, raw), calls.length);
|
|
178
|
+
return MDTable_1.default.factory({
|
|
179
|
+
title: methodName,
|
|
180
|
+
heading: ['start time', 'end time', 'duration', 'args'],
|
|
181
|
+
leftAlignedCols: [3],
|
|
182
|
+
rows: underscore_1.default.map(calls, (call) => [
|
|
183
|
+
toDuration(call.startTime - react_native_performance_1.default.timeOrigin, raw),
|
|
184
|
+
toDuration(call.startTime + call.duration - timeOrigin, raw),
|
|
185
|
+
toDuration(call.duration, raw),
|
|
186
|
+
underscore_1.default.map(call.detail.args, String).join(', ').slice(0, 60), // Restrict cell width to 60 chars max
|
|
187
|
+
]),
|
|
188
|
+
});
|
|
189
|
+
})
|
|
205
190
|
.value();
|
|
206
|
-
|
|
207
191
|
if (/csv|json|string/i.test(format)) {
|
|
208
192
|
const allTables = [tableSummary, ...methodCallTables];
|
|
209
|
-
|
|
210
|
-
return _.map(allTables, (table) => {
|
|
193
|
+
return underscore_1.default.map(allTables, (table) => {
|
|
211
194
|
switch (format.toLowerCase()) {
|
|
212
195
|
case 'csv':
|
|
213
196
|
return table.toCSV();
|
|
@@ -218,11 +201,8 @@ function printMetrics({raw = false, format = 'console', methods} = {}) {
|
|
|
218
201
|
}
|
|
219
202
|
}).join('\n\n');
|
|
220
203
|
}
|
|
221
|
-
|
|
222
204
|
const lastComplete = lastCompleteCall && toDuration(lastCompleteCall.startTime + lastCompleteCall.duration - timeOrigin, raw);
|
|
223
|
-
|
|
224
205
|
const mainOutput = ['### Onyx Benchmark', ` - Total: ${toDuration(totalTime, raw)}`, ` - Last call finished at: ${lastComplete || 'N/A'}`, '', tableSummary.toString()];
|
|
225
|
-
|
|
226
206
|
/* eslint-disable no-console */
|
|
227
207
|
console.info(mainOutput.join('\n'));
|
|
228
208
|
methodCallTables.forEach((table) => {
|
|
@@ -232,20 +212,18 @@ function printMetrics({raw = false, format = 'console', methods} = {}) {
|
|
|
232
212
|
});
|
|
233
213
|
/* eslint-enable */
|
|
234
214
|
}
|
|
235
|
-
|
|
215
|
+
exports.printMetrics = printMetrics;
|
|
236
216
|
/**
|
|
237
217
|
* Clears all collected metrics.
|
|
238
218
|
*/
|
|
239
219
|
function resetMetrics() {
|
|
240
|
-
const {summaries} = getMetrics();
|
|
241
|
-
|
|
242
|
-
_.chain(summaries)
|
|
220
|
+
const { summaries } = getMetrics();
|
|
221
|
+
underscore_1.default.chain(summaries)
|
|
243
222
|
.map((summary) => summary.calls)
|
|
244
223
|
.flatten()
|
|
245
224
|
.each((measure) => {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
225
|
+
react_native_performance_1.default.clearMarks(measure.detail.alias);
|
|
226
|
+
react_native_performance_1.default.clearMeasures(measure.name);
|
|
227
|
+
});
|
|
249
228
|
}
|
|
250
|
-
|
|
251
|
-
export {decorateWithMetrics, getMetrics, resetMetrics, printMetrics};
|
|
229
|
+
exports.resetMetrics = resetMetrics;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const SQLiteStorage_1 = __importDefault(require("./providers/SQLiteStorage"));
|
|
7
|
+
exports.default = SQLiteStorage_1.default;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default webStorage;
|
|
2
|
+
declare const webStorage: {
|
|
3
|
+
/**
|
|
4
|
+
* @param {Function} onStorageKeyChanged Storage synchronization mechanism keeping all opened tabs in sync
|
|
5
|
+
*/
|
|
6
|
+
keepInstancesSync(onStorageKeyChanged: Function): void;
|
|
7
|
+
setItem: (key: string, value: any) => Promise<void>;
|
|
8
|
+
multiGet: (keysParam: string[]) => Promise<[key, value][]>;
|
|
9
|
+
multiMerge: (pairs: [key, value][]) => Promise<void>;
|
|
10
|
+
mergeItem(key: string, _changes: any, modifiedData: any): Promise<void>;
|
|
11
|
+
multiSet: (pairs: [key, value][]) => Promise<void>;
|
|
12
|
+
clear: () => Promise<void>;
|
|
13
|
+
setMemoryOnlyKeys: () => void;
|
|
14
|
+
getAllKeys: () => Promise<string[]>;
|
|
15
|
+
getItem: (key: string) => Promise<any>;
|
|
16
|
+
removeItem: (key: string) => Promise<void>;
|
|
17
|
+
removeItems: (keysParam: any[]) => Promise<any>;
|
|
18
|
+
getDatabaseSize(): Promise<number>;
|
|
19
|
+
};
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
6
|
/**
|
|
2
7
|
* This file is here to wrap IDBKeyVal with a layer that provides data-changed events like the ones that exist
|
|
3
8
|
* when using LocalStorage APIs in the browser. These events are great because multiple tabs can listen for when
|
|
4
9
|
* data changes and then stay up-to-date with everything happening in Onyx.
|
|
5
10
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
const underscore_1 = __importDefault(require("underscore"));
|
|
12
|
+
const IDBKeyVal_1 = __importDefault(require("./providers/IDBKeyVal"));
|
|
9
13
|
const SYNC_ONYX = 'SYNC_ONYX';
|
|
10
|
-
|
|
11
14
|
/**
|
|
12
15
|
* Raise an event thorough `localStorage` to let other tabs know a value changed
|
|
13
16
|
* @param {String} onyxKey
|
|
@@ -16,59 +19,46 @@ function raiseStorageSyncEvent(onyxKey) {
|
|
|
16
19
|
global.localStorage.setItem(SYNC_ONYX, onyxKey);
|
|
17
20
|
global.localStorage.removeItem(SYNC_ONYX, onyxKey);
|
|
18
21
|
}
|
|
19
|
-
|
|
20
22
|
function raiseStorageSyncManyKeysEvent(onyxKeys) {
|
|
21
|
-
|
|
23
|
+
underscore_1.default.each(onyxKeys, (onyxKey) => {
|
|
22
24
|
raiseStorageSyncEvent(onyxKey);
|
|
23
25
|
});
|
|
24
26
|
}
|
|
25
|
-
|
|
26
|
-
const webStorage = {
|
|
27
|
-
...Storage,
|
|
28
|
-
|
|
27
|
+
const webStorage = Object.assign(Object.assign({}, IDBKeyVal_1.default), {
|
|
29
28
|
/**
|
|
30
29
|
* @param {Function} onStorageKeyChanged Storage synchronization mechanism keeping all opened tabs in sync
|
|
31
30
|
*/
|
|
32
31
|
keepInstancesSync(onStorageKeyChanged) {
|
|
33
32
|
// Override set, remove and clear to raise storage events that we intercept in other tabs
|
|
34
|
-
this.setItem = (key, value) =>
|
|
35
|
-
|
|
36
|
-
this.
|
|
37
|
-
|
|
38
|
-
this.removeItems = (keys) => Storage.removeItems(keys).then(() => raiseStorageSyncManyKeysEvent(keys));
|
|
39
|
-
|
|
40
|
-
this.mergeItem = (key, batchedChanges, modifiedData) => Storage.mergeItem(key, batchedChanges, modifiedData).then(() => raiseStorageSyncEvent(key));
|
|
41
|
-
|
|
33
|
+
this.setItem = (key, value) => IDBKeyVal_1.default.setItem(key, value).then(() => raiseStorageSyncEvent(key));
|
|
34
|
+
this.removeItem = (key) => IDBKeyVal_1.default.removeItem(key).then(() => raiseStorageSyncEvent(key));
|
|
35
|
+
this.removeItems = (keys) => IDBKeyVal_1.default.removeItems(keys).then(() => raiseStorageSyncManyKeysEvent(keys));
|
|
36
|
+
this.mergeItem = (key, batchedChanges, modifiedData) => IDBKeyVal_1.default.mergeItem(key, batchedChanges, modifiedData).then(() => raiseStorageSyncEvent(key));
|
|
42
37
|
// If we just call Storage.clear other tabs will have no idea which keys were available previously
|
|
43
38
|
// so that they can call keysChanged for them. That's why we iterate over every key and raise a storage sync
|
|
44
39
|
// event for each one
|
|
45
40
|
this.clear = () => {
|
|
46
41
|
let allKeys;
|
|
47
|
-
|
|
48
42
|
// The keys must be retrieved before storage is cleared or else the list of keys would be empty
|
|
49
|
-
return
|
|
43
|
+
return IDBKeyVal_1.default.getAllKeys()
|
|
50
44
|
.then((keys) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
.then(() =>
|
|
45
|
+
allKeys = keys;
|
|
46
|
+
})
|
|
47
|
+
.then(() => IDBKeyVal_1.default.clear())
|
|
54
48
|
.then(() => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
// Now that storage is cleared, the storage sync event can happen which is a more atomic action
|
|
50
|
+
// for other browser tabs
|
|
51
|
+
underscore_1.default.each(allKeys, raiseStorageSyncEvent);
|
|
52
|
+
});
|
|
59
53
|
};
|
|
60
|
-
|
|
61
54
|
// This listener will only be triggered by events coming from other tabs
|
|
62
55
|
global.addEventListener('storage', (event) => {
|
|
63
56
|
// Ignore events that don't originate from the SYNC_ONYX logic
|
|
64
57
|
if (event.key !== SYNC_ONYX || !event.newValue) {
|
|
65
58
|
return;
|
|
66
59
|
}
|
|
67
|
-
|
|
68
60
|
const onyxKey = event.newValue;
|
|
69
|
-
|
|
61
|
+
IDBKeyVal_1.default.getItem(onyxKey).then((value) => onStorageKeyChanged(onyxKey, value));
|
|
70
62
|
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
export default webStorage;
|
|
63
|
+
} });
|
|
64
|
+
exports.default = webStorage;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export default idbKeyvalMockSpy;
|
|
2
|
+
declare namespace idbKeyvalMockSpy {
|
|
3
|
+
export { set as idbKeyvalSet };
|
|
4
|
+
export let setItem: jest.Mock<Promise<any>, [key?: any, value?: any]>;
|
|
5
|
+
export let getItem: jest.Mock<Promise<any>, [key?: any]>;
|
|
6
|
+
export let removeItem: jest.Mock<Promise<void>, [key?: any]>;
|
|
7
|
+
export let removeItems: jest.Mock<Promise<void>, [keys?: any]>;
|
|
8
|
+
export let clear: jest.Mock<Promise<void>, []>;
|
|
9
|
+
export let getAllKeys: jest.Mock<Promise<any>, []>;
|
|
10
|
+
export let config: jest.Mock<void, []>;
|
|
11
|
+
export let multiGet: jest.Mock<Promise<any>, [keys?: any]>;
|
|
12
|
+
export let multiSet: jest.Mock<Promise<any>, [pairs?: any]>;
|
|
13
|
+
export let multiMerge: jest.Mock<Promise<{}>, [pairs?: any]>;
|
|
14
|
+
export let mergeItem: jest.Mock<Promise<any>, [key?: any, _changes?: any, modifiedData?: any]>;
|
|
15
|
+
export let getStorageMap: jest.Mock<{}, []>;
|
|
16
|
+
export let setInitialMockData: jest.Mock<void, [data?: any]>;
|
|
17
|
+
export let getDatabaseSize: jest.Mock<Promise<{
|
|
18
|
+
bytesRemaining: number;
|
|
19
|
+
bytesUsed: number;
|
|
20
|
+
}>, []>;
|
|
21
|
+
export let setMemoryOnlyKeys: jest.Mock<void, []>;
|
|
22
|
+
}
|
|
23
|
+
declare const set: jest.Mock<Promise<any>, [key?: any, value?: any]>;
|