@ansight/react-native 1.3.0-preview.9 → 1.4.0-preview.3
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 +109 -39
- package/android/build.gradle +2 -2
- package/android/src/main/kotlin/ai/ansight/reactnative/AnsightReactNativeModule.kt +91 -24
- package/index.d.ts +97 -23
- package/index.js +231 -80
- package/ios/AnsightReactNative.swift +97 -31
- package/ios/AnsightReactNativeModule.m +4 -0
- package/network.js +764 -0
- package/package.json +8 -2
- package/react-inspection-hook.js +76 -0
- package/react-tree-geometry.js +61 -0
- package/react-tree-semantics.js +33 -0
- package/session-properties.js +151 -0
package/index.js
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
const { ensureReactInspectionHook } = require("./react-inspection-hook");
|
|
4
|
+
const { createReactCoordinateSpace } = require("./react-tree-geometry");
|
|
5
|
+
const { reactSemanticRole, reactSupportedActions } = require("./react-tree-semantics");
|
|
6
|
+
|
|
7
|
+
// Production React Native renderers only look for the DevTools hook once, when
|
|
8
|
+
// the renderer module initializes. Install a minimal root tracker while this
|
|
9
|
+
// package is loading so Fabric and Paper can report their roots before the app's
|
|
10
|
+
// first render. Development runtimes keep their full React DevTools hook.
|
|
11
|
+
if (typeof __DEV__ === "undefined" || !__DEV__) {
|
|
12
|
+
ensureReactInspectionHook(typeof global !== "undefined" ? global : undefined);
|
|
13
|
+
}
|
|
14
|
+
|
|
3
15
|
const {
|
|
4
16
|
AppState,
|
|
17
|
+
Dimensions,
|
|
5
18
|
NativeEventEmitter,
|
|
6
19
|
NativeModules,
|
|
7
20
|
Platform,
|
|
@@ -10,6 +23,15 @@ const {
|
|
|
10
23
|
findNodeHandle,
|
|
11
24
|
processColor,
|
|
12
25
|
} = require("react-native");
|
|
26
|
+
const { version: reactVersion } = require("react");
|
|
27
|
+
const {
|
|
28
|
+
createAutomaticSessionProperties,
|
|
29
|
+
mergeSessionProperties,
|
|
30
|
+
} = require("./session-properties");
|
|
31
|
+
const {
|
|
32
|
+
installNetworkCapture: installNetworkCaptureCore,
|
|
33
|
+
sanitizeNetworkRequest,
|
|
34
|
+
} = require("./network");
|
|
13
35
|
|
|
14
36
|
const nativeModule = NativeModules.AnsightReactNative;
|
|
15
37
|
|
|
@@ -33,6 +55,9 @@ const hostConnectionStatusListeners = new Set();
|
|
|
33
55
|
let lastHostConnectionStatusKey = null;
|
|
34
56
|
const logListeners = new Set();
|
|
35
57
|
let logEventSubscription = null;
|
|
58
|
+
let networkCaptureSubscription = null;
|
|
59
|
+
let networkCaptureRegistration = null;
|
|
60
|
+
let networkConnectionEventSubscription = null;
|
|
36
61
|
const REACT_COMPONENT_TREE_TOOL_ID = "react.get_component_tree";
|
|
37
62
|
const REACT_SHADOW_TREE_TOOL_ID = "react.get_shadow_tree";
|
|
38
63
|
|
|
@@ -44,7 +69,28 @@ function normalizePairingPayload(payload) {
|
|
|
44
69
|
}
|
|
45
70
|
|
|
46
71
|
function normalizeOptions(options = {}) {
|
|
47
|
-
|
|
72
|
+
const normalized = {
|
|
73
|
+
...options,
|
|
74
|
+
customProperties: mergeSessionProperties(
|
|
75
|
+
automaticSessionProperties(),
|
|
76
|
+
options.customProperties
|
|
77
|
+
),
|
|
78
|
+
};
|
|
79
|
+
delete normalized.networkCapture;
|
|
80
|
+
return normalized;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function automaticSessionProperties() {
|
|
84
|
+
return createAutomaticSessionProperties({
|
|
85
|
+
platform: Platform,
|
|
86
|
+
reactVersion,
|
|
87
|
+
runtimeGlobal: global,
|
|
88
|
+
developmentMode: typeof __DEV__ !== "undefined" && __DEV__,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function automaticSessionPropertyValue(group, key) {
|
|
93
|
+
return automaticSessionProperties()[group]?.[key];
|
|
48
94
|
}
|
|
49
95
|
|
|
50
96
|
function cloneOptions(options = {}) {
|
|
@@ -73,6 +119,17 @@ function cloneOptions(options = {}) {
|
|
|
73
119
|
if (options.hostConnection) {
|
|
74
120
|
clone.hostConnection = { ...options.hostConnection };
|
|
75
121
|
}
|
|
122
|
+
if (options.networkCapture && typeof options.networkCapture === "object") {
|
|
123
|
+
clone.networkCapture = {
|
|
124
|
+
...options.networkCapture,
|
|
125
|
+
additionalSensitiveHeaderNames: options.networkCapture.additionalSensitiveHeaderNames
|
|
126
|
+
? [...options.networkCapture.additionalSensitiveHeaderNames]
|
|
127
|
+
: undefined,
|
|
128
|
+
additionalSensitiveQueryParameterNames: options.networkCapture.additionalSensitiveQueryParameterNames
|
|
129
|
+
? [...options.networkCapture.additionalSensitiveQueryParameterNames]
|
|
130
|
+
: undefined,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
76
133
|
if (options.secureStorage) {
|
|
77
134
|
clone.secureStorage = {
|
|
78
135
|
...options.secureStorage,
|
|
@@ -339,6 +396,52 @@ class AnsightOptionsBuilder {
|
|
|
339
396
|
return this;
|
|
340
397
|
}
|
|
341
398
|
|
|
399
|
+
withNetworkCapture(networkCapture = {}) {
|
|
400
|
+
this._options.networkCapture = { ...networkCapture };
|
|
401
|
+
return this;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
withNetworkRequestBodies(maximumBodyBytes) {
|
|
405
|
+
if (!this._options.networkCapture || typeof this._options.networkCapture !== "object") return this;
|
|
406
|
+
const current = this._options.networkCapture;
|
|
407
|
+
this._options.networkCapture = {
|
|
408
|
+
...current,
|
|
409
|
+
captureRequestBody: true,
|
|
410
|
+
...(maximumBodyBytes == null ? {} : { maximumBodyBytes }),
|
|
411
|
+
};
|
|
412
|
+
return this;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
withoutNetworkRequestBodies() {
|
|
416
|
+
if (!this._options.networkCapture || typeof this._options.networkCapture !== "object") return this;
|
|
417
|
+
const current = this._options.networkCapture;
|
|
418
|
+
this._options.networkCapture = { ...current, captureRequestBody: false };
|
|
419
|
+
return this;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
withNetworkResponseBodies(maximumBodyBytes) {
|
|
423
|
+
if (!this._options.networkCapture || typeof this._options.networkCapture !== "object") return this;
|
|
424
|
+
const current = this._options.networkCapture;
|
|
425
|
+
this._options.networkCapture = {
|
|
426
|
+
...current,
|
|
427
|
+
captureResponseBody: true,
|
|
428
|
+
...(maximumBodyBytes == null ? {} : { maximumBodyBytes }),
|
|
429
|
+
};
|
|
430
|
+
return this;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
withoutNetworkResponseBodies() {
|
|
434
|
+
if (!this._options.networkCapture || typeof this._options.networkCapture !== "object") return this;
|
|
435
|
+
const current = this._options.networkCapture;
|
|
436
|
+
this._options.networkCapture = { ...current, captureResponseBody: false };
|
|
437
|
+
return this;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
withoutNetworkCapture() {
|
|
441
|
+
this._options.networkCapture = false;
|
|
442
|
+
return this;
|
|
443
|
+
}
|
|
444
|
+
|
|
342
445
|
withToolGuard(toolGuard) {
|
|
343
446
|
this._options.toolGuard = toolGuard;
|
|
344
447
|
return this;
|
|
@@ -581,6 +684,7 @@ function addHostConnectionStatusListener(listener, options = {}) {
|
|
|
581
684
|
|
|
582
685
|
async function notifyAfterHostConnectionChange(operation) {
|
|
583
686
|
const result = await operation();
|
|
687
|
+
await refreshNetworkCaptureConnection();
|
|
584
688
|
await emitHostConnectionStatusChangedIfNeeded();
|
|
585
689
|
return result;
|
|
586
690
|
}
|
|
@@ -811,7 +915,6 @@ function artifactDefinitionPayload(providerId, definition) {
|
|
|
811
915
|
metadata: normalizedMetadata(definition.metadata),
|
|
812
916
|
content: artifactContentDescriptor(definition),
|
|
813
917
|
argumentsSchema: definition.argumentsSchema || { type: "object", additionalProperties: true },
|
|
814
|
-
security: definition.security || { level: "moderate", implications: ["metadata_disclosure"] },
|
|
815
918
|
};
|
|
816
919
|
}
|
|
817
920
|
|
|
@@ -962,7 +1065,7 @@ function artifactToolDefinitions() {
|
|
|
962
1065
|
name: "Query Artifacts",
|
|
963
1066
|
description: "Queries app-provided artifact providers and currently requestable artifact definitions.",
|
|
964
1067
|
category: "artifacts",
|
|
965
|
-
|
|
1068
|
+
policy: "read",
|
|
966
1069
|
keywords: ["artifact", "artifacts", "query", "catalog", "provider", "export", "snapshot"],
|
|
967
1070
|
argumentsSchema: {
|
|
968
1071
|
type: "object",
|
|
@@ -974,18 +1077,13 @@ function artifactToolDefinitions() {
|
|
|
974
1077
|
},
|
|
975
1078
|
},
|
|
976
1079
|
resultSchema: genericObject,
|
|
977
|
-
security: {
|
|
978
|
-
level: "moderate",
|
|
979
|
-
summary: "Discovers app-provided artifact definitions and descriptive metadata.",
|
|
980
|
-
implications: ["metadata_disclosure"],
|
|
981
|
-
},
|
|
982
1080
|
},
|
|
983
1081
|
{
|
|
984
1082
|
id: ARTIFACT_REQUEST_TOOL_ID,
|
|
985
1083
|
name: "Request Artifact",
|
|
986
1084
|
description: "Requests an app-provided artifact snapshot and streams it to the host.",
|
|
987
1085
|
category: "artifacts",
|
|
988
|
-
|
|
1086
|
+
policy: "read",
|
|
989
1087
|
keywords: ["artifact", "artifacts", "request", "export", "snapshot", "binary", "stream"],
|
|
990
1088
|
argumentsSchema: {
|
|
991
1089
|
type: "object",
|
|
@@ -999,11 +1097,6 @@ function artifactToolDefinitions() {
|
|
|
999
1097
|
required: ["providerId", "artifactId"],
|
|
1000
1098
|
},
|
|
1001
1099
|
resultSchema: genericObject,
|
|
1002
|
-
security: {
|
|
1003
|
-
level: "high",
|
|
1004
|
-
summary: "Requests and exports an app-provided artifact snapshot.",
|
|
1005
|
-
implications: ["exports_app_data", "binary_transfer"],
|
|
1006
|
-
},
|
|
1007
1100
|
},
|
|
1008
1101
|
];
|
|
1009
1102
|
}
|
|
@@ -1440,36 +1533,16 @@ function summarizeProps(props) {
|
|
|
1440
1533
|
return summary;
|
|
1441
1534
|
}
|
|
1442
1535
|
|
|
1443
|
-
function reactSemanticRole(type, props, fiberTag) {
|
|
1444
|
-
const declared = props && (props.accessibilityRole || props.role);
|
|
1445
|
-
if (declared) return String(declared).toLowerCase();
|
|
1446
|
-
if (fiberTag === 6 || /text/i.test(type)) return "text";
|
|
1447
|
-
if (/button|pressable|touchable/i.test(type)) return "button";
|
|
1448
|
-
if (/textinput/i.test(type)) return "textbox";
|
|
1449
|
-
if (/switch/i.test(type)) return "switch";
|
|
1450
|
-
if (/scrollview|flatlist|sectionlist/i.test(type)) return "scrollview";
|
|
1451
|
-
return "view";
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1454
|
-
function reactSupportedActions(type, props) {
|
|
1455
|
-
const actions = [];
|
|
1456
|
-
if (props && typeof props.onPress === "function") actions.push("tap");
|
|
1457
|
-
if (props && (typeof props.onChangeText === "function" || /textinput/i.test(type))) {
|
|
1458
|
-
actions.push("typeText", "focus");
|
|
1459
|
-
}
|
|
1460
|
-
if (/scrollview|flatlist|sectionlist/i.test(type) || (props && typeof props.onScroll === "function")) {
|
|
1461
|
-
actions.push("scroll", "swipe");
|
|
1462
|
-
}
|
|
1463
|
-
return actions;
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
1536
|
function applyReactTargetability(node, fiber, props, type) {
|
|
1467
1537
|
const style = StyleSheet && typeof StyleSheet.flatten === "function"
|
|
1468
1538
|
? StyleSheet.flatten(props && props.style)
|
|
1469
1539
|
: props && props.style;
|
|
1470
1540
|
node.text = node.label || (node.visual && node.visual.text) || null;
|
|
1471
|
-
node.role = reactSemanticRole(type, props, fiber.tag);
|
|
1472
1541
|
node.supportedActions = reactSupportedActions(type, props);
|
|
1542
|
+
node.role = reactSemanticRole(type, props, fiber.tag);
|
|
1543
|
+
if (node.role === "view" && node.supportedActions.includes("tap")) {
|
|
1544
|
+
node.role = "button";
|
|
1545
|
+
}
|
|
1473
1546
|
node.visible = !(style && style.display === "none") && !(props && props.accessibilityElementsHidden);
|
|
1474
1547
|
node.enabled = !(props && (props.disabled === true || props.accessibilityState && props.accessibilityState.disabled === true));
|
|
1475
1548
|
node.focusable = !!(props && props.focusable) || node.supportedActions.includes("focus");
|
|
@@ -1823,6 +1896,7 @@ async function captureReactVisualTree(rawOptions = {}) {
|
|
|
1823
1896
|
source: "react",
|
|
1824
1897
|
adapter: "react.fiber",
|
|
1825
1898
|
treeKind: "component",
|
|
1899
|
+
coordinateSpace: createReactCoordinateSpace(Dimensions, context.nodesWithNativeTags),
|
|
1826
1900
|
capturedAtUtc: new Date().toISOString(),
|
|
1827
1901
|
hookAvailable: roots.hookAvailable,
|
|
1828
1902
|
renderers: roots.renderers,
|
|
@@ -1883,6 +1957,7 @@ async function captureReactShadowTree(rawOptions = {}) {
|
|
|
1883
1957
|
source: "react-native",
|
|
1884
1958
|
adapter: "react-native.host-fiber",
|
|
1885
1959
|
treeKind: "shadow",
|
|
1960
|
+
coordinateSpace: createReactCoordinateSpace(Dimensions, context.nodesWithNativeTags),
|
|
1886
1961
|
capturedAtUtc: new Date().toISOString(),
|
|
1887
1962
|
hookAvailable: roots.hookAvailable,
|
|
1888
1963
|
renderers: roots.renderers,
|
|
@@ -1985,7 +2060,7 @@ function reactToolDefinitions(enableActions) {
|
|
|
1985
2060
|
name: "Get React Component Tree",
|
|
1986
2061
|
description: "Captures the live React Fiber component tree for the current React Native runtime.",
|
|
1987
2062
|
category: "react",
|
|
1988
|
-
|
|
2063
|
+
policy: "read",
|
|
1989
2064
|
keywords: ["react", "react-native", "fiber", "component", "component-tree"],
|
|
1990
2065
|
argumentsSchema: {
|
|
1991
2066
|
type: "object",
|
|
@@ -1998,18 +2073,13 @@ function reactToolDefinitions(enableActions) {
|
|
|
1998
2073
|
},
|
|
1999
2074
|
},
|
|
2000
2075
|
resultSchema: { type: "object", additionalProperties: true },
|
|
2001
|
-
security: {
|
|
2002
|
-
level: "high",
|
|
2003
|
-
summary: "Inspects the React component tree and optionally sanitized props/state.",
|
|
2004
|
-
implications: ["inspects_runtime_state", "metadata_disclosure"],
|
|
2005
|
-
},
|
|
2006
2076
|
},
|
|
2007
2077
|
{
|
|
2008
2078
|
id: REACT_SHADOW_TREE_TOOL_ID,
|
|
2009
2079
|
name: "Get React Shadow Tree",
|
|
2010
2080
|
description: "Captures the committed React Native host tree with composite components flattened out.",
|
|
2011
2081
|
category: "react",
|
|
2012
|
-
|
|
2082
|
+
policy: "read",
|
|
2013
2083
|
keywords: ["react", "react-native", "host", "shadow", "shadow-tree", "layout"],
|
|
2014
2084
|
argumentsSchema: {
|
|
2015
2085
|
type: "object",
|
|
@@ -2021,18 +2091,13 @@ function reactToolDefinitions(enableActions) {
|
|
|
2021
2091
|
},
|
|
2022
2092
|
},
|
|
2023
2093
|
resultSchema: { type: "object", additionalProperties: true },
|
|
2024
|
-
security: {
|
|
2025
|
-
level: "high",
|
|
2026
|
-
summary: "Inspects the React Native host tree and optionally sanitized host props.",
|
|
2027
|
-
implications: ["inspects_runtime_state", "metadata_disclosure"],
|
|
2028
|
-
},
|
|
2029
2094
|
},
|
|
2030
2095
|
{
|
|
2031
2096
|
id: "react.find_components",
|
|
2032
2097
|
name: "Find React Components",
|
|
2033
2098
|
description: "Searches the live React component tree by component type, text, testID, nativeID, or accessibility label.",
|
|
2034
2099
|
category: "react",
|
|
2035
|
-
|
|
2100
|
+
policy: "read",
|
|
2036
2101
|
keywords: ["react", "search", "component", "testid", "accessibility"],
|
|
2037
2102
|
argumentsSchema: {
|
|
2038
2103
|
type: "object",
|
|
@@ -2046,18 +2111,13 @@ function reactToolDefinitions(enableActions) {
|
|
|
2046
2111
|
},
|
|
2047
2112
|
},
|
|
2048
2113
|
resultSchema: { type: "object", additionalProperties: true },
|
|
2049
|
-
security: {
|
|
2050
|
-
level: "high",
|
|
2051
|
-
summary: "Searches React runtime metadata and may reveal UI text.",
|
|
2052
|
-
implications: ["inspects_runtime_state", "metadata_disclosure"],
|
|
2053
|
-
},
|
|
2054
2114
|
},
|
|
2055
2115
|
{
|
|
2056
2116
|
id: "react.get_component",
|
|
2057
2117
|
name: "Get React Component",
|
|
2058
2118
|
description: "Returns a single React component node from the current React visual tree.",
|
|
2059
2119
|
category: "react",
|
|
2060
|
-
|
|
2120
|
+
policy: "read",
|
|
2061
2121
|
keywords: ["react", "component", "props", "fiber"],
|
|
2062
2122
|
argumentsSchema: {
|
|
2063
2123
|
type: "object",
|
|
@@ -2070,25 +2130,15 @@ function reactToolDefinitions(enableActions) {
|
|
|
2070
2130
|
required: ["nodeId"],
|
|
2071
2131
|
},
|
|
2072
2132
|
resultSchema: { type: "object", additionalProperties: true },
|
|
2073
|
-
security: {
|
|
2074
|
-
level: "high",
|
|
2075
|
-
summary: "Reads one React component node and optionally sanitized props/state.",
|
|
2076
|
-
implications: ["inspects_runtime_state", "metadata_disclosure"],
|
|
2077
|
-
},
|
|
2078
2133
|
},
|
|
2079
2134
|
{
|
|
2080
2135
|
id: "react.get_navigation_state",
|
|
2081
2136
|
name: "Get React Navigation State",
|
|
2082
2137
|
description: "Returns the configured React Navigation ref state when installReactTools receives a navigationRef.",
|
|
2083
2138
|
category: "react",
|
|
2084
|
-
|
|
2139
|
+
policy: "read",
|
|
2085
2140
|
keywords: ["react", "navigation", "route", "screen"],
|
|
2086
2141
|
resultSchema: { type: "object", additionalProperties: true },
|
|
2087
|
-
security: {
|
|
2088
|
-
level: "medium",
|
|
2089
|
-
summary: "Reads navigation route metadata from a configured navigation ref.",
|
|
2090
|
-
implications: ["inspects_runtime_state", "metadata_disclosure"],
|
|
2091
|
-
},
|
|
2092
2142
|
},
|
|
2093
2143
|
];
|
|
2094
2144
|
|
|
@@ -2098,7 +2148,7 @@ function reactToolDefinitions(enableActions) {
|
|
|
2098
2148
|
name: "Invoke React Component Action",
|
|
2099
2149
|
description: "Invokes an allow-listed function prop on a React component, such as onPress.",
|
|
2100
2150
|
category: "react",
|
|
2101
|
-
|
|
2151
|
+
policy: "write",
|
|
2102
2152
|
keywords: ["react", "component", "action", "onpress"],
|
|
2103
2153
|
argumentsSchema: {
|
|
2104
2154
|
type: "object",
|
|
@@ -2109,11 +2159,6 @@ function reactToolDefinitions(enableActions) {
|
|
|
2109
2159
|
required: ["nodeId", "prop"],
|
|
2110
2160
|
},
|
|
2111
2161
|
resultSchema: { type: "object", additionalProperties: true },
|
|
2112
|
-
security: {
|
|
2113
|
-
level: "critical",
|
|
2114
|
-
summary: "Invokes app code through a React prop function.",
|
|
2115
|
-
implications: ["invokes_app_code", "mutates_runtime_state"],
|
|
2116
|
-
},
|
|
2117
2162
|
});
|
|
2118
2163
|
}
|
|
2119
2164
|
|
|
@@ -2212,7 +2257,7 @@ function installReactTools(options = {}) {
|
|
|
2212
2257
|
errorCode: "react_action_not_found",
|
|
2213
2258
|
};
|
|
2214
2259
|
}
|
|
2215
|
-
await action();
|
|
2260
|
+
await action(args.value);
|
|
2216
2261
|
return {
|
|
2217
2262
|
success: true,
|
|
2218
2263
|
message: `Invoked React component action '${prop}'.`,
|
|
@@ -2313,6 +2358,7 @@ function installErrorHandlers(options = {}) {
|
|
|
2313
2358
|
|
|
2314
2359
|
async function initialize(options = {}) {
|
|
2315
2360
|
const result = await nativeModule.initialize(normalizeOptions(options));
|
|
2361
|
+
await configureNetworkCapture(options.networkCapture);
|
|
2316
2362
|
if (options.lifecycle !== false) {
|
|
2317
2363
|
startAppStateTracking();
|
|
2318
2364
|
}
|
|
@@ -2322,6 +2368,7 @@ async function initialize(options = {}) {
|
|
|
2322
2368
|
|
|
2323
2369
|
async function initializeAndActivate(options = {}) {
|
|
2324
2370
|
const result = await nativeModule.initializeAndActivate(normalizeOptions(options));
|
|
2371
|
+
await configureNetworkCapture(options.networkCapture);
|
|
2325
2372
|
if (options.lifecycle !== false) {
|
|
2326
2373
|
startAppStateTracking();
|
|
2327
2374
|
}
|
|
@@ -2396,6 +2443,93 @@ function recordCrashCandidate(input = {}) {
|
|
|
2396
2443
|
});
|
|
2397
2444
|
}
|
|
2398
2445
|
|
|
2446
|
+
function recordNetworkRequest(input, sanitizationOptions = {}) {
|
|
2447
|
+
const sanitized = sanitizeNetworkRequest(input, sanitizationOptions, global);
|
|
2448
|
+
if (!sanitized) {
|
|
2449
|
+
return Promise.resolve({ success: false, message: "Network request capture was suppressed by the sanitizer." });
|
|
2450
|
+
}
|
|
2451
|
+
return nativeModule.recordNetworkRequest(sanitized);
|
|
2452
|
+
}
|
|
2453
|
+
|
|
2454
|
+
function installNetworkCapture(options = {}) {
|
|
2455
|
+
uninstallNetworkCapture();
|
|
2456
|
+
const registration = { options };
|
|
2457
|
+
networkCaptureRegistration = registration;
|
|
2458
|
+
ensureNetworkConnectionEventSubscription();
|
|
2459
|
+
void refreshNetworkCaptureConnection();
|
|
2460
|
+
return {
|
|
2461
|
+
remove() {
|
|
2462
|
+
if (networkCaptureRegistration === registration) {
|
|
2463
|
+
uninstallNetworkCapture();
|
|
2464
|
+
}
|
|
2465
|
+
},
|
|
2466
|
+
};
|
|
2467
|
+
}
|
|
2468
|
+
|
|
2469
|
+
function uninstallNetworkCapture() {
|
|
2470
|
+
networkCaptureRegistration = null;
|
|
2471
|
+
if (networkConnectionEventSubscription) {
|
|
2472
|
+
networkConnectionEventSubscription.remove();
|
|
2473
|
+
networkConnectionEventSubscription = null;
|
|
2474
|
+
}
|
|
2475
|
+
detachNetworkCapture();
|
|
2476
|
+
}
|
|
2477
|
+
|
|
2478
|
+
function detachNetworkCapture() {
|
|
2479
|
+
if (!networkCaptureSubscription) return;
|
|
2480
|
+
networkCaptureSubscription.remove();
|
|
2481
|
+
networkCaptureSubscription = null;
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
async function refreshNetworkCaptureConnection() {
|
|
2485
|
+
const registration = networkCaptureRegistration;
|
|
2486
|
+
if (!registration) {
|
|
2487
|
+
detachNetworkCapture();
|
|
2488
|
+
return;
|
|
2489
|
+
}
|
|
2490
|
+
try {
|
|
2491
|
+
const status = await nativeModule.hostConnectionStatus();
|
|
2492
|
+
if (networkCaptureRegistration !== registration) return;
|
|
2493
|
+
applyNetworkConnectionStatus(status);
|
|
2494
|
+
} catch {
|
|
2495
|
+
if (networkCaptureRegistration === registration) detachNetworkCapture();
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
function ensureNetworkConnectionEventSubscription() {
|
|
2500
|
+
if (networkConnectionEventSubscription) return;
|
|
2501
|
+
const emitter = new NativeEventEmitter(nativeModule);
|
|
2502
|
+
networkConnectionEventSubscription = emitter.addListener(
|
|
2503
|
+
"AnsightHostConnectionStatus",
|
|
2504
|
+
applyNetworkConnectionStatus,
|
|
2505
|
+
);
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
function applyNetworkConnectionStatus(status) {
|
|
2509
|
+
const registration = networkCaptureRegistration;
|
|
2510
|
+
if (!registration || !status || status.isConnected !== true) {
|
|
2511
|
+
detachNetworkCapture();
|
|
2512
|
+
return;
|
|
2513
|
+
}
|
|
2514
|
+
if (!networkCaptureSubscription) {
|
|
2515
|
+
networkCaptureSubscription = installNetworkCaptureCore({
|
|
2516
|
+
globalObject: global,
|
|
2517
|
+
options: registration.options,
|
|
2518
|
+
sourcePrefix: "react-native",
|
|
2519
|
+
capture: (request) => nativeModule.recordNetworkRequest(request),
|
|
2520
|
+
});
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
async function configureNetworkCapture(value) {
|
|
2525
|
+
uninstallNetworkCapture();
|
|
2526
|
+
if (!value) return;
|
|
2527
|
+
const registration = { options: typeof value === "object" ? value : {} };
|
|
2528
|
+
networkCaptureRegistration = registration;
|
|
2529
|
+
ensureNetworkConnectionEventSubscription();
|
|
2530
|
+
await refreshNetworkCaptureConnection();
|
|
2531
|
+
}
|
|
2532
|
+
|
|
2399
2533
|
function screenViewed(name, details) {
|
|
2400
2534
|
return nativeModule.screenViewed(name, details || {});
|
|
2401
2535
|
}
|
|
@@ -2439,6 +2573,7 @@ const Ansight = {
|
|
|
2439
2573
|
event: recordEvent,
|
|
2440
2574
|
recordEvent,
|
|
2441
2575
|
recordCrashCandidate,
|
|
2576
|
+
recordNetworkRequest,
|
|
2442
2577
|
screenViewed,
|
|
2443
2578
|
trackRoute,
|
|
2444
2579
|
setAppLifecycleState: (state) => nativeModule.setAppLifecycleState(state),
|
|
@@ -2473,12 +2608,21 @@ const Ansight = {
|
|
|
2473
2608
|
captureScreenFrame: (options = {}) => nativeModule.captureScreenFrame(options || {}),
|
|
2474
2609
|
enableTouchCapture: () => nativeModule.enableTouchCapture(),
|
|
2475
2610
|
disableTouchCapture: () => nativeModule.disableTouchCapture(),
|
|
2476
|
-
updateSessionProperties: (properties) => nativeModule.updateSessionProperties(
|
|
2477
|
-
|
|
2478
|
-
|
|
2611
|
+
updateSessionProperties: (properties) => nativeModule.updateSessionProperties(
|
|
2612
|
+
mergeSessionProperties(automaticSessionProperties(), properties || {})
|
|
2613
|
+
),
|
|
2614
|
+
clearSessionProperties: () => nativeModule.updateSessionProperties(automaticSessionProperties()),
|
|
2615
|
+
updateCustomProperties: (properties) => nativeModule.updateSessionProperties(
|
|
2616
|
+
mergeSessionProperties(automaticSessionProperties(), properties || {})
|
|
2617
|
+
),
|
|
2479
2618
|
registerCustomProperty: (group, key, value) => nativeModule.registerCustomProperty(group, key, value),
|
|
2480
|
-
removeCustomProperty: (group, key) =>
|
|
2481
|
-
|
|
2619
|
+
removeCustomProperty: (group, key) => {
|
|
2620
|
+
const automaticValue = automaticSessionPropertyValue(group, key);
|
|
2621
|
+
return automaticValue == null
|
|
2622
|
+
? nativeModule.removeCustomProperty(group, key)
|
|
2623
|
+
: nativeModule.registerCustomProperty(group, key, automaticValue);
|
|
2624
|
+
},
|
|
2625
|
+
clearCustomProperties: () => nativeModule.updateSessionProperties(automaticSessionProperties()),
|
|
2482
2626
|
registerTool,
|
|
2483
2627
|
unregisterTool,
|
|
2484
2628
|
registerArtifactProvider,
|
|
@@ -2500,6 +2644,9 @@ const Ansight = {
|
|
|
2500
2644
|
installReactTools,
|
|
2501
2645
|
uninstallReactTools,
|
|
2502
2646
|
installErrorHandlers,
|
|
2647
|
+
installNetworkCapture,
|
|
2648
|
+
uninstallNetworkCapture,
|
|
2649
|
+
sanitizeNetworkRequest,
|
|
2503
2650
|
createReactNavigationTracker,
|
|
2504
2651
|
platform: Platform.OS,
|
|
2505
2652
|
};
|
|
@@ -2518,3 +2665,7 @@ module.exports.registerArtifactProviders = registerArtifactProviders;
|
|
|
2518
2665
|
module.exports.unregisterArtifactProvider = unregisterArtifactProvider;
|
|
2519
2666
|
module.exports.listRegisteredArtifactProviders = listRegisteredArtifactProviders;
|
|
2520
2667
|
module.exports.clearArtifactProviders = clearArtifactProviders;
|
|
2668
|
+
module.exports.recordNetworkRequest = recordNetworkRequest;
|
|
2669
|
+
module.exports.installNetworkCapture = installNetworkCapture;
|
|
2670
|
+
module.exports.uninstallNetworkCapture = uninstallNetworkCapture;
|
|
2671
|
+
module.exports.sanitizeNetworkRequest = sanitizeNetworkRequest;
|