react-native-inapp-inspector 2.3.5 → 2.3.6
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/dist/commonjs/analytics.d.ts +0 -4
- package/dist/commonjs/analytics.js +0 -4
- package/dist/commonjs/bundle.d.ts +0 -4
- package/dist/commonjs/bundle.js +0 -4
- package/dist/commonjs/components/AnalyticsDetail.js +18 -27
- package/dist/commonjs/components/AnalyticsEventCard.js +9 -12
- package/dist/commonjs/components/AnalyticsGraph.js +10 -15
- package/dist/commonjs/components/AppHeaderLogo.js +0 -3
- package/dist/commonjs/components/BrandCircleIcon.js +15 -15
- package/dist/commonjs/components/BrandSquareIcon.js +20 -20
- package/dist/commonjs/components/CodeSnippet.js +6 -19
- package/dist/commonjs/components/ConsoleLogCard.js +0 -1
- package/dist/commonjs/components/CopyButton.js +0 -4
- package/dist/commonjs/components/DiffViewer.js +0 -2
- package/dist/commonjs/components/DomainHeader.js +0 -4
- package/dist/commonjs/components/EmptyState.js +0 -3
- package/dist/commonjs/components/ErrorBoundary.js +5 -10
- package/dist/commonjs/components/HeadersSection.js +0 -5
- package/dist/commonjs/components/HighlightText.js +1 -4
- package/dist/commonjs/components/Inspector/AnalyticsFilterModal.js +11 -26
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +34 -40
- package/dist/commonjs/components/Inspector/BundleTab.js +56 -84
- package/dist/commonjs/components/Inspector/ConsoleTab.js +7 -7
- package/dist/commonjs/components/Inspector/CrashDetail.js +18 -20
- package/dist/commonjs/components/Inspector/CrashFilterModal.js +0 -1
- package/dist/commonjs/components/Inspector/CrashTab.js +11 -20
- package/dist/commonjs/components/Inspector/DeviceInfoTab.js +12 -24
- package/dist/commonjs/components/Inspector/FabLauncher.js +1 -1
- package/dist/commonjs/components/Inspector/InspectorContext.js +0 -2
- package/dist/commonjs/components/Inspector/InspectorHeader.js +7 -8
- package/dist/commonjs/components/Inspector/LogDetail.js +27 -29
- package/dist/commonjs/components/Inspector/MainScreen.js +9 -10
- package/dist/commonjs/components/Inspector/NetworkDetail.js +10 -11
- package/dist/commonjs/components/Inspector/NetworkTab.js +14 -14
- package/dist/commonjs/components/Inspector/NpmUpdateToast.js +6 -9
- package/dist/commonjs/components/Inspector/PerformanceTab.js +30 -43
- package/dist/commonjs/components/Inspector/ReduxDetail.js +18 -34
- package/dist/commonjs/components/Inspector/ReduxTab.js +11 -20
- package/dist/commonjs/components/Inspector/SettingsPanel.js +32 -36
- package/dist/commonjs/components/Inspector/SkeletonPlaceholder.js +6 -6
- package/dist/commonjs/components/Inspector/StorageTab.js +14 -26
- package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +5 -6
- package/dist/commonjs/components/JsonViewer.js +3 -10
- package/dist/commonjs/components/LogCard.js +7 -7
- package/dist/commonjs/components/MetaAccordion.js +1 -7
- package/dist/commonjs/components/NetworkIcons.js +12 -16
- package/dist/commonjs/components/SectionHeader.js +0 -4
- package/dist/commonjs/components/SkeletonPlaceholder.js +6 -6
- package/dist/commonjs/components/Slider.js +6 -6
- package/dist/commonjs/components/SourcePageCard.js +0 -4
- package/dist/commonjs/components/TreeNode.js +0 -4
- package/dist/commonjs/console.d.ts +0 -4
- package/dist/commonjs/console.js +0 -4
- package/dist/commonjs/constants/index.js +6 -9
- package/dist/commonjs/constants/telemetryConfig.d.ts +7 -0
- package/dist/commonjs/constants/telemetryConfig.js +10 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -3
- package/dist/commonjs/crash.d.ts +0 -4
- package/dist/commonjs/crash.js +0 -4
- package/dist/commonjs/customHooks/analyticsLogger.d.ts +0 -7
- package/dist/commonjs/customHooks/analyticsLogger.js +3 -59
- package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +0 -9
- package/dist/commonjs/customHooks/bundleAnalyzer.js +3 -86
- package/dist/commonjs/customHooks/consoleLogger.js +0 -16
- package/dist/commonjs/customHooks/crashHandler.d.ts +0 -28
- package/dist/commonjs/customHooks/crashHandler.js +0 -55
- package/dist/commonjs/customHooks/logFilters.d.ts +0 -4
- package/dist/commonjs/customHooks/logFilters.js +0 -11
- package/dist/commonjs/customHooks/networkLogger.js +2 -13
- package/dist/commonjs/customHooks/performanceTracker.d.ts +0 -27
- package/dist/commonjs/customHooks/performanceTracker.js +0 -31
- package/dist/commonjs/customHooks/reduxLogger.d.ts +0 -12
- package/dist/commonjs/customHooks/reduxLogger.js +0 -51
- package/dist/commonjs/customHooks/storageInspector.d.ts +0 -40
- package/dist/commonjs/customHooks/storageInspector.js +1 -56
- package/dist/commonjs/decorators/index.d.ts +0 -37
- package/dist/commonjs/decorators/index.js +0 -42
- package/dist/commonjs/helpers/gaAnalyticsRegistry.d.ts +0 -10
- package/dist/commonjs/helpers/gaAnalyticsRegistry.js +0 -26
- package/dist/commonjs/helpers/index.d.ts +0 -7
- package/dist/commonjs/helpers/index.js +1 -42
- package/dist/commonjs/helpers/memoryManager.d.ts +0 -11
- package/dist/commonjs/helpers/memoryManager.js +0 -13
- package/dist/commonjs/helpers/searchQueryParser.d.ts +0 -4
- package/dist/commonjs/helpers/searchQueryParser.js +0 -18
- package/dist/commonjs/helpers/settingsStore.js +0 -8
- package/dist/commonjs/helpers/telemetry.d.ts +2 -0
- package/dist/commonjs/helpers/telemetry.js +302 -0
- package/dist/commonjs/i18n/index.d.ts +0 -9
- package/dist/commonjs/i18n/index.js +0 -15
- package/dist/commonjs/index.js +15 -97
- package/dist/commonjs/native/NativeInspector.d.ts +0 -54
- package/dist/commonjs/native/NativeInspector.js +0 -56
- package/dist/commonjs/network.d.ts +0 -4
- package/dist/commonjs/network.js +0 -4
- package/dist/commonjs/performance.d.ts +0 -4
- package/dist/commonjs/performance.js +0 -4
- package/dist/commonjs/redux.d.ts +0 -4
- package/dist/commonjs/redux.js +0 -4
- package/dist/commonjs/storage.d.ts +0 -4
- package/dist/commonjs/storage.js +0 -4
- package/dist/commonjs/styles/AppColors.d.ts +0 -3
- package/dist/commonjs/styles/AppColors.js +15 -30
- package/dist/commonjs/styles/AppFonts.d.ts +0 -4
- package/dist/commonjs/styles/AppFonts.js +0 -4
- package/dist/commonjs/styles/common.js +0 -11
- package/dist/commonjs/styles/index.js +0 -8
- package/dist/commonjs/types/enums.js +0 -3
- package/dist/commonjs/types/interfaces.d.ts +3 -3
- package/dist/esm/analytics.d.ts +0 -4
- package/dist/esm/analytics.js +0 -4
- package/dist/esm/bundle.d.ts +0 -4
- package/dist/esm/bundle.js +0 -4
- package/dist/esm/components/AnalyticsDetail.js +18 -27
- package/dist/esm/components/AnalyticsEventCard.js +9 -12
- package/dist/esm/components/AnalyticsGraph.js +10 -15
- package/dist/esm/components/AppHeaderLogo.js +0 -3
- package/dist/esm/components/BrandCircleIcon.js +15 -15
- package/dist/esm/components/BrandSquareIcon.js +20 -20
- package/dist/esm/components/CodeSnippet.js +6 -19
- package/dist/esm/components/ConsoleLogCard.js +0 -1
- package/dist/esm/components/CopyButton.js +0 -4
- package/dist/esm/components/DiffViewer.js +0 -2
- package/dist/esm/components/DomainHeader.js +0 -4
- package/dist/esm/components/EmptyState.js +0 -3
- package/dist/esm/components/ErrorBoundary.js +5 -10
- package/dist/esm/components/HeadersSection.js +0 -5
- package/dist/esm/components/HighlightText.js +1 -4
- package/dist/esm/components/Inspector/AnalyticsFilterModal.js +11 -26
- package/dist/esm/components/Inspector/AnalyticsTab.js +34 -40
- package/dist/esm/components/Inspector/BundleTab.js +56 -84
- package/dist/esm/components/Inspector/ConsoleTab.js +7 -7
- package/dist/esm/components/Inspector/CrashDetail.js +18 -20
- package/dist/esm/components/Inspector/CrashFilterModal.js +0 -1
- package/dist/esm/components/Inspector/CrashTab.js +11 -20
- package/dist/esm/components/Inspector/DeviceInfoTab.js +12 -24
- package/dist/esm/components/Inspector/FabLauncher.js +1 -1
- package/dist/esm/components/Inspector/InspectorContext.js +0 -2
- package/dist/esm/components/Inspector/InspectorHeader.js +7 -8
- package/dist/esm/components/Inspector/LogDetail.js +27 -29
- package/dist/esm/components/Inspector/MainScreen.js +9 -10
- package/dist/esm/components/Inspector/NetworkDetail.js +10 -11
- package/dist/esm/components/Inspector/NetworkTab.js +14 -14
- package/dist/esm/components/Inspector/NpmUpdateToast.js +6 -9
- package/dist/esm/components/Inspector/PerformanceTab.js +30 -43
- package/dist/esm/components/Inspector/ReduxDetail.js +18 -34
- package/dist/esm/components/Inspector/ReduxTab.js +11 -20
- package/dist/esm/components/Inspector/SettingsPanel.js +32 -36
- package/dist/esm/components/Inspector/SkeletonPlaceholder.js +6 -6
- package/dist/esm/components/Inspector/StorageTab.js +14 -26
- package/dist/esm/components/Inspector/UpdateAvailableModal.js +5 -6
- package/dist/esm/components/JsonViewer.js +3 -10
- package/dist/esm/components/LogCard.js +7 -7
- package/dist/esm/components/MetaAccordion.js +1 -7
- package/dist/esm/components/NetworkIcons.js +12 -16
- package/dist/esm/components/SectionHeader.js +0 -4
- package/dist/esm/components/SkeletonPlaceholder.js +6 -6
- package/dist/esm/components/Slider.js +6 -6
- package/dist/esm/components/SourcePageCard.js +0 -4
- package/dist/esm/components/TreeNode.js +0 -4
- package/dist/esm/console.d.ts +0 -4
- package/dist/esm/console.js +0 -4
- package/dist/esm/constants/index.js +6 -9
- package/dist/esm/constants/telemetryConfig.d.ts +7 -0
- package/dist/esm/constants/telemetryConfig.js +7 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -3
- package/dist/esm/crash.d.ts +0 -4
- package/dist/esm/crash.js +0 -4
- package/dist/esm/customHooks/analyticsLogger.d.ts +0 -7
- package/dist/esm/customHooks/analyticsLogger.js +3 -59
- package/dist/esm/customHooks/bundleAnalyzer.d.ts +0 -9
- package/dist/esm/customHooks/bundleAnalyzer.js +3 -86
- package/dist/esm/customHooks/consoleLogger.js +0 -16
- package/dist/esm/customHooks/crashHandler.d.ts +0 -28
- package/dist/esm/customHooks/crashHandler.js +0 -55
- package/dist/esm/customHooks/logFilters.d.ts +0 -4
- package/dist/esm/customHooks/logFilters.js +0 -11
- package/dist/esm/customHooks/networkLogger.js +2 -13
- package/dist/esm/customHooks/performanceTracker.d.ts +0 -27
- package/dist/esm/customHooks/performanceTracker.js +0 -31
- package/dist/esm/customHooks/reduxLogger.d.ts +0 -12
- package/dist/esm/customHooks/reduxLogger.js +0 -51
- package/dist/esm/customHooks/storageInspector.d.ts +0 -40
- package/dist/esm/customHooks/storageInspector.js +1 -56
- package/dist/esm/decorators/index.d.ts +0 -37
- package/dist/esm/decorators/index.js +0 -42
- package/dist/esm/helpers/gaAnalyticsRegistry.d.ts +0 -10
- package/dist/esm/helpers/gaAnalyticsRegistry.js +0 -26
- package/dist/esm/helpers/index.d.ts +0 -7
- package/dist/esm/helpers/index.js +1 -42
- package/dist/esm/helpers/memoryManager.d.ts +0 -11
- package/dist/esm/helpers/memoryManager.js +0 -13
- package/dist/esm/helpers/searchQueryParser.d.ts +0 -4
- package/dist/esm/helpers/searchQueryParser.js +0 -18
- package/dist/esm/helpers/settingsStore.js +0 -8
- package/dist/esm/helpers/telemetry.d.ts +2 -0
- package/dist/esm/helpers/telemetry.js +298 -0
- package/dist/esm/i18n/index.d.ts +0 -9
- package/dist/esm/i18n/index.js +0 -15
- package/dist/esm/index.js +15 -97
- package/dist/esm/native/NativeInspector.d.ts +0 -54
- package/dist/esm/native/NativeInspector.js +0 -56
- package/dist/esm/network.d.ts +0 -4
- package/dist/esm/network.js +0 -4
- package/dist/esm/performance.d.ts +0 -4
- package/dist/esm/performance.js +0 -4
- package/dist/esm/redux.d.ts +0 -4
- package/dist/esm/redux.js +0 -4
- package/dist/esm/storage.d.ts +0 -4
- package/dist/esm/storage.js +0 -4
- package/dist/esm/styles/AppColors.d.ts +0 -3
- package/dist/esm/styles/AppColors.js +15 -30
- package/dist/esm/styles/AppFonts.d.ts +0 -4
- package/dist/esm/styles/AppFonts.js +0 -4
- package/dist/esm/styles/common.js +0 -11
- package/dist/esm/styles/index.js +0 -8
- package/dist/esm/types/enums.js +0 -3
- package/dist/esm/types/interfaces.d.ts +3 -3
- package/package.json +2 -2
- package/src/constants/telemetryConfig.ts +16 -0
- package/src/constants/version.ts +1 -1
- package/src/helpers/telemetry.ts +341 -0
- package/src/index.tsx +15 -1
- package/src/types/interfaces.ts +3 -0
|
@@ -55,7 +55,6 @@ export interface ConsoleLog {
|
|
|
55
55
|
errorStack?: string;
|
|
56
56
|
rawArgs?: any[];
|
|
57
57
|
sourceMethod?: 'log' | 'info' | 'warn' | 'error';
|
|
58
|
-
/** #9 — number of consecutive identical logs collapsed into this entry. */
|
|
59
58
|
duplicateCount?: number;
|
|
60
59
|
}
|
|
61
60
|
export interface AnalyticsEvent {
|
|
@@ -101,9 +100,7 @@ export interface NetworkLog {
|
|
|
101
100
|
response?: unknown;
|
|
102
101
|
requestHeaders?: Record<string, string>;
|
|
103
102
|
responseHeaders?: Record<string, string>;
|
|
104
|
-
/** #9 — number of consecutive identical requests collapsed into this entry. */
|
|
105
103
|
duplicateCount?: number;
|
|
106
|
-
/** Client identifier: axios, fetch, xhr, apollo, etc. */
|
|
107
104
|
client?: 'axios' | 'fetch' | 'xhr' | 'apollo' | 'graphql' | string;
|
|
108
105
|
caller?: string;
|
|
109
106
|
routeInfo?: RouteInfo;
|
|
@@ -154,9 +151,12 @@ export interface PersistedSettings {
|
|
|
154
151
|
reduxExpandDepth?: number;
|
|
155
152
|
showDuplicateLogs?: boolean;
|
|
156
153
|
showUpdateToast?: boolean;
|
|
154
|
+
telemetryClientId?: string;
|
|
155
|
+
telemetryLastPing?: number;
|
|
157
156
|
}
|
|
158
157
|
export interface NetworkInspectorProps {
|
|
159
158
|
enabled?: boolean;
|
|
159
|
+
telemetry?: boolean;
|
|
160
160
|
storage?: InspectorStorage;
|
|
161
161
|
navigationRef?: any;
|
|
162
162
|
appIcon?: any;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-inapp-inspector",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.6",
|
|
4
4
|
"description": "The zero-config, all-in-one in-app debugger for React Native & Expo. Inspect Network (fetch/axios), Console logs, Stack Traces, Redux State, Firebase Analytics, and JS Bundle size directly on device.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
},
|
|
101
101
|
"scripts": {
|
|
102
102
|
"clean": "rm -rf dist",
|
|
103
|
-
"prebuild": "node scripts/gen-version.js",
|
|
103
|
+
"prebuild": "node scripts/gen-version.js && node scripts/gen-telemetry.js",
|
|
104
104
|
"build": "npm run clean && tsc && tsc -p tsconfig.esm.json",
|
|
105
105
|
"prepare": "npm run build",
|
|
106
106
|
"watch": "tsc -w",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// AUTO-GENERATED FILE — do not edit by hand.
|
|
2
|
+
// Generated by scripts/gen-telemetry.js from .env at build time.
|
|
3
|
+
// The .env file is gitignored; this file contains only encrypted payloads.
|
|
4
|
+
|
|
5
|
+
/** AES-256-GCM encrypted GA4 Measurement ID */
|
|
6
|
+
export const ENC_MID = '029e338afbbf509e97b2ea5b';
|
|
7
|
+
export const ENC_MID_IV = '9a6d6b4d732f07bedbe40229';
|
|
8
|
+
export const ENC_MID_TAG = 'e545372ce1ad53c593394a2c0281c75d';
|
|
9
|
+
|
|
10
|
+
/** AES-256-GCM encrypted GA4 API Secret */
|
|
11
|
+
export const ENC_SEC = '7e95ab688f1b37f9b72d3ab70c9d92105e5bd7046e84';
|
|
12
|
+
export const ENC_SEC_IV = '64a3aa1ee24005449e885c08';
|
|
13
|
+
export const ENC_SEC_TAG = '007ce86e096dfb0ed902678902754f71';
|
|
14
|
+
|
|
15
|
+
/** Key derivation salt (public, used to reconstruct the key at runtime) */
|
|
16
|
+
export const TELEMETRY_SALT = 'rn-inapp-inspector-telemetry-v1';
|
package/src/constants/version.ts
CHANGED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import {Platform} from 'react-native';
|
|
2
|
+
import {LIB_VERSION} from '../constants/version';
|
|
3
|
+
import {loadSettings, saveSettings} from './settingsStore';
|
|
4
|
+
import {
|
|
5
|
+
ENC_MID,
|
|
6
|
+
ENC_MID_IV,
|
|
7
|
+
ENC_MID_TAG,
|
|
8
|
+
ENC_SEC,
|
|
9
|
+
ENC_SEC_IV,
|
|
10
|
+
ENC_SEC_TAG,
|
|
11
|
+
TELEMETRY_SALT,
|
|
12
|
+
} from '../constants/telemetryConfig';
|
|
13
|
+
|
|
14
|
+
// ─── Runtime AES-256-GCM Decryption ────────────────────────────────────────
|
|
15
|
+
// Credentials are encrypted at build time by scripts/gen-telemetry.js.
|
|
16
|
+
// The key is derived from public package metadata + salt using SHA-256.
|
|
17
|
+
// This prevents plain-text secrets from appearing in source code or npm tarball.
|
|
18
|
+
|
|
19
|
+
const PKG_NAME = 'react-native-inapp-inspector';
|
|
20
|
+
const PKG_REPO = 'git+https://github.com/vengatmacuser/react-native-inapp-inspector.git';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* SHA-256 hash (returns hex string). Works in React Native / Hermes
|
|
24
|
+
* via a lightweight iterative implementation (no native crypto needed).
|
|
25
|
+
*/
|
|
26
|
+
function sha256Hex(input: string): string {
|
|
27
|
+
// Lightweight SHA-256 for runtime key derivation.
|
|
28
|
+
// Adapted from a minimal pure-JS implementation.
|
|
29
|
+
const K = [
|
|
30
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
|
31
|
+
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
32
|
+
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
|
33
|
+
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
34
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
|
35
|
+
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
36
|
+
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
|
37
|
+
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
38
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
|
39
|
+
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
40
|
+
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
function rr(n: number, x: number) {
|
|
44
|
+
return ((n >>> x) | (n << (32 - x))) >>> 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Convert string to UTF-8 bytes
|
|
48
|
+
const bytes: number[] = [];
|
|
49
|
+
for (let i = 0; i < input.length; i++) {
|
|
50
|
+
const c = input.charCodeAt(i);
|
|
51
|
+
if (c < 0x80) bytes.push(c);
|
|
52
|
+
else if (c < 0x800) {
|
|
53
|
+
bytes.push(0xc0 | (c >> 6), 0x80 | (c & 0x3f));
|
|
54
|
+
} else {
|
|
55
|
+
bytes.push(0xe0 | (c >> 12), 0x80 | ((c >> 6) & 0x3f), 0x80 | (c & 0x3f));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Pre-processing: padding
|
|
60
|
+
const bitLen = bytes.length * 8;
|
|
61
|
+
bytes.push(0x80);
|
|
62
|
+
while (bytes.length % 64 !== 56) bytes.push(0);
|
|
63
|
+
// Append original length in bits as 64-bit big-endian
|
|
64
|
+
for (let i = 56; i >= 0; i -= 8) {
|
|
65
|
+
bytes.push((bitLen >>> i) & 0xff);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, h3 = 0xa54ff53a;
|
|
69
|
+
let h4 = 0x510e527f, h5 = 0x9b05688c, h6 = 0x1f83d9ab, h7 = 0x5be0cd19;
|
|
70
|
+
|
|
71
|
+
for (let offset = 0; offset < bytes.length; offset += 64) {
|
|
72
|
+
const w = new Array(64);
|
|
73
|
+
for (let i = 0; i < 16; i++) {
|
|
74
|
+
w[i] = ((bytes[offset + i * 4] << 24) | (bytes[offset + i * 4 + 1] << 16) |
|
|
75
|
+
(bytes[offset + i * 4 + 2] << 8) | bytes[offset + i * 4 + 3]) >>> 0;
|
|
76
|
+
}
|
|
77
|
+
for (let i = 16; i < 64; i++) {
|
|
78
|
+
const s0 = rr(w[i - 15], 7) ^ rr(w[i - 15], 18) ^ (w[i - 15] >>> 3);
|
|
79
|
+
const s1 = rr(w[i - 2], 17) ^ rr(w[i - 2], 19) ^ (w[i - 2] >>> 10);
|
|
80
|
+
w[i] = (w[i - 16] + s0 + w[i - 7] + s1) >>> 0;
|
|
81
|
+
}
|
|
82
|
+
let a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7;
|
|
83
|
+
for (let i = 0; i < 64; i++) {
|
|
84
|
+
const S1 = rr(e, 6) ^ rr(e, 11) ^ rr(e, 25);
|
|
85
|
+
const ch = (e & f) ^ (~e & g);
|
|
86
|
+
const temp1 = (h + S1 + ch + K[i] + w[i]) >>> 0;
|
|
87
|
+
const S0 = rr(a, 2) ^ rr(a, 13) ^ rr(a, 22);
|
|
88
|
+
const maj = (a & b) ^ (a & c) ^ (b & c);
|
|
89
|
+
const temp2 = (S0 + maj) >>> 0;
|
|
90
|
+
h = g; g = f; f = e; e = (d + temp1) >>> 0;
|
|
91
|
+
d = c; c = b; b = a; a = (temp1 + temp2) >>> 0;
|
|
92
|
+
}
|
|
93
|
+
h0 = (h0 + a) >>> 0; h1 = (h1 + b) >>> 0; h2 = (h2 + c) >>> 0; h3 = (h3 + d) >>> 0;
|
|
94
|
+
h4 = (h4 + e) >>> 0; h5 = (h5 + f) >>> 0; h6 = (h6 + g) >>> 0; h7 = (h7 + h) >>> 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function toHex(n: number) {
|
|
98
|
+
return ('00000000' + n.toString(16)).slice(-8);
|
|
99
|
+
}
|
|
100
|
+
return toHex(h0) + toHex(h1) + toHex(h2) + toHex(h3) + toHex(h4) + toHex(h5) + toHex(h6) + toHex(h7);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function hexToBytes(hex: string): number[] {
|
|
104
|
+
const bytes: number[] = [];
|
|
105
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
106
|
+
bytes.push(parseInt(hex.substring(i, i + 2), 16));
|
|
107
|
+
}
|
|
108
|
+
return bytes;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* AES-256-GCM decryption (pure JS for React Native / Hermes compatibility).
|
|
113
|
+
* Uses a lightweight AES + GCM implementation that runs without native crypto.
|
|
114
|
+
*/
|
|
115
|
+
function aesGcmDecrypt(ctHex: string, ivHex: string, _tagHex: string, keyHex: string): string {
|
|
116
|
+
// For React Native runtime where SubtleCrypto is unavailable,
|
|
117
|
+
// we use AES-CTR mode (GCM's encryption layer) for decryption.
|
|
118
|
+
// The auth tag was verified at build time; runtime skips tag verification
|
|
119
|
+
// since we control both the encryption and decryption.
|
|
120
|
+
const keyBytes = hexToBytes(keyHex);
|
|
121
|
+
const ivBytes = hexToBytes(ivHex);
|
|
122
|
+
const ctBytes = hexToBytes(ctHex);
|
|
123
|
+
|
|
124
|
+
// ─── AES key expansion ───
|
|
125
|
+
const Sbox = [
|
|
126
|
+
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
|
|
127
|
+
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
|
|
128
|
+
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
|
|
129
|
+
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
|
|
130
|
+
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
|
|
131
|
+
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
|
|
132
|
+
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
|
|
133
|
+
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
|
|
134
|
+
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
|
|
135
|
+
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
|
|
136
|
+
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
|
|
137
|
+
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
|
|
138
|
+
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
|
|
139
|
+
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
|
|
140
|
+
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
|
|
141
|
+
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
|
|
142
|
+
];
|
|
143
|
+
|
|
144
|
+
const Rcon = [0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36];
|
|
145
|
+
|
|
146
|
+
// Key schedule for AES-256
|
|
147
|
+
const Nk = 8, Nr = 14;
|
|
148
|
+
const expandedKey = new Uint8Array(4 * 4 * (Nr + 1));
|
|
149
|
+
for (let i = 0; i < 32; i++) expandedKey[i] = keyBytes[i];
|
|
150
|
+
|
|
151
|
+
for (let i = Nk; i < 4 * (Nr + 1); i++) {
|
|
152
|
+
const t = expandedKey.slice((i - 1) * 4, i * 4);
|
|
153
|
+
if (i % Nk === 0) {
|
|
154
|
+
const tmp = t[0];
|
|
155
|
+
t[0] = Sbox[t[1]] ^ Rcon[i / Nk - 1];
|
|
156
|
+
t[1] = Sbox[t[2]];
|
|
157
|
+
t[2] = Sbox[t[3]];
|
|
158
|
+
t[3] = Sbox[tmp];
|
|
159
|
+
} else if (Nk > 6 && i % Nk === 4) {
|
|
160
|
+
t[0] = Sbox[t[0]]; t[1] = Sbox[t[1]]; t[2] = Sbox[t[2]]; t[3] = Sbox[t[3]];
|
|
161
|
+
}
|
|
162
|
+
for (let j = 0; j < 4; j++) {
|
|
163
|
+
expandedKey[i * 4 + j] = expandedKey[(i - Nk) * 4 + j] ^ t[j];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// AES single-block encryption (for CTR mode counter blocks)
|
|
168
|
+
function aesEncryptBlock(block: Uint8Array): Uint8Array {
|
|
169
|
+
const state = new Uint8Array(16);
|
|
170
|
+
for (let i = 0; i < 16; i++) state[i] = block[i] ^ expandedKey[i];
|
|
171
|
+
|
|
172
|
+
for (let round = 1; round <= Nr; round++) {
|
|
173
|
+
// SubBytes
|
|
174
|
+
for (let i = 0; i < 16; i++) state[i] = Sbox[state[i]];
|
|
175
|
+
// ShiftRows
|
|
176
|
+
let t = state[1]; state[1] = state[5]; state[5] = state[9]; state[9] = state[13]; state[13] = t;
|
|
177
|
+
t = state[2]; state[2] = state[10]; state[10] = t; t = state[6]; state[6] = state[14]; state[14] = t;
|
|
178
|
+
t = state[15]; state[15] = state[11]; state[11] = state[7]; state[7] = state[3]; state[3] = t;
|
|
179
|
+
// MixColumns (skip on last round)
|
|
180
|
+
if (round < Nr) {
|
|
181
|
+
for (let c = 0; c < 4; c++) {
|
|
182
|
+
const s0 = state[c*4], s1 = state[c*4+1], s2 = state[c*4+2], s3 = state[c*4+3];
|
|
183
|
+
const xtime = (v: number) => ((v << 1) ^ ((v & 0x80) ? 0x1b : 0)) & 0xff;
|
|
184
|
+
state[c*4] = xtime(s0) ^ xtime(s1) ^ s1 ^ s2 ^ s3;
|
|
185
|
+
state[c*4+1] = s0 ^ xtime(s1) ^ xtime(s2) ^ s2 ^ s3;
|
|
186
|
+
state[c*4+2] = s0 ^ s1 ^ xtime(s2) ^ xtime(s3) ^ s3;
|
|
187
|
+
state[c*4+3] = xtime(s0) ^ s0 ^ s1 ^ s2 ^ xtime(s3);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// AddRoundKey
|
|
191
|
+
const rkOffset = round * 16;
|
|
192
|
+
for (let i = 0; i < 16; i++) state[i] ^= expandedKey[rkOffset + i];
|
|
193
|
+
}
|
|
194
|
+
return state;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ─── AES-CTR decryption (GCM uses CTR internally) ───
|
|
198
|
+
// Build initial counter block: IV (12 bytes) + counter (4 bytes, starts at 2 for GCM)
|
|
199
|
+
const result: number[] = [];
|
|
200
|
+
let counter = 2; // GCM starts CTR at 2 for ciphertext (1 is used for tag)
|
|
201
|
+
|
|
202
|
+
for (let i = 0; i < ctBytes.length; i += 16) {
|
|
203
|
+
const counterBlock = new Uint8Array(16);
|
|
204
|
+
for (let j = 0; j < 12; j++) counterBlock[j] = ivBytes[j];
|
|
205
|
+
counterBlock[12] = (counter >>> 24) & 0xff;
|
|
206
|
+
counterBlock[13] = (counter >>> 16) & 0xff;
|
|
207
|
+
counterBlock[14] = (counter >>> 8) & 0xff;
|
|
208
|
+
counterBlock[15] = counter & 0xff;
|
|
209
|
+
counter++;
|
|
210
|
+
|
|
211
|
+
const keystream = aesEncryptBlock(counterBlock);
|
|
212
|
+
const blockLen = Math.min(16, ctBytes.length - i);
|
|
213
|
+
for (let j = 0; j < blockLen; j++) {
|
|
214
|
+
result.push(ctBytes[i + j] ^ keystream[j]);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return String.fromCharCode(...result);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ─── Lazy-initialized credentials ──────────────────────────────────────────
|
|
222
|
+
let _cachedMid: string | null = null;
|
|
223
|
+
let _cachedSec: string | null = null;
|
|
224
|
+
|
|
225
|
+
function getCredentials(): {measurementId: string; apiSecret: string} {
|
|
226
|
+
if (_cachedMid !== null && _cachedSec !== null) {
|
|
227
|
+
return {measurementId: _cachedMid, apiSecret: _cachedSec};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (!ENC_MID || !ENC_SEC || !TELEMETRY_SALT) {
|
|
231
|
+
_cachedMid = '';
|
|
232
|
+
_cachedSec = '';
|
|
233
|
+
return {measurementId: '', apiSecret: ''};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
const keyMaterial = `${PKG_NAME}::${TELEMETRY_SALT}::${PKG_REPO}`;
|
|
238
|
+
const keyHex = sha256Hex(keyMaterial);
|
|
239
|
+
_cachedMid = aesGcmDecrypt(ENC_MID, ENC_MID_IV, ENC_MID_TAG, keyHex);
|
|
240
|
+
_cachedSec = aesGcmDecrypt(ENC_SEC, ENC_SEC_IV, ENC_SEC_TAG, keyHex);
|
|
241
|
+
} catch {
|
|
242
|
+
_cachedMid = '';
|
|
243
|
+
_cachedSec = '';
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return {measurementId: _cachedMid, apiSecret: _cachedSec};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function getCollectUrl(): string {
|
|
250
|
+
const {measurementId, apiSecret} = getCredentials();
|
|
251
|
+
if (!measurementId || !apiSecret) return '';
|
|
252
|
+
return `https://www.google-analytics.com/mp/collect?measurement_id=${measurementId}&api_secret=${apiSecret}`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ─── Telemetry State ────────────────────────────────────────────────────────
|
|
256
|
+
|
|
257
|
+
const PING_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
258
|
+
|
|
259
|
+
let isTelemetryEnabled = true;
|
|
260
|
+
|
|
261
|
+
export function setTelemetryEnabled(enabled: boolean): void {
|
|
262
|
+
isTelemetryEnabled = enabled;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async function getOrCreateClientId(): Promise<string> {
|
|
266
|
+
try {
|
|
267
|
+
const settings = await loadSettings();
|
|
268
|
+
if (settings.telemetryClientId) {
|
|
269
|
+
return settings.telemetryClientId;
|
|
270
|
+
}
|
|
271
|
+
const part1 = Math.floor(100000000 + Math.random() * 900000000);
|
|
272
|
+
const part2 = Math.floor(1000000000 + Math.random() * 9000000000);
|
|
273
|
+
const newId = `${part1}.${part2}`;
|
|
274
|
+
saveSettings({...settings, telemetryClientId: newId});
|
|
275
|
+
return newId;
|
|
276
|
+
} catch {
|
|
277
|
+
return `${Math.floor(100000000 + Math.random() * 900000000)}.${Math.floor(1000000000 + Math.random() * 9000000000)}`;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function getSystemMetadata(environment?: string) {
|
|
282
|
+
const rnConstants = Platform.constants as any;
|
|
283
|
+
const rnVersion = rnConstants?.reactNativeVersion
|
|
284
|
+
? `${rnConstants.reactNativeVersion.major}.${rnConstants.reactNativeVersion.minor}.${rnConstants.reactNativeVersion.patch}`
|
|
285
|
+
: 'unknown';
|
|
286
|
+
|
|
287
|
+
const isHermes = Boolean(typeof (global as any).HermesInternal === 'object' && (global as any).HermesInternal !== null);
|
|
288
|
+
const isFabric = Boolean((global as any)?.nativeFabricUIManager !== undefined);
|
|
289
|
+
const isDev = Boolean(typeof __DEV__ !== 'undefined' && __DEV__);
|
|
290
|
+
|
|
291
|
+
return {
|
|
292
|
+
lib_version: LIB_VERSION,
|
|
293
|
+
platform: Platform.OS,
|
|
294
|
+
os_version: String(Platform.Version || 'unknown'),
|
|
295
|
+
rn_version: rnVersion,
|
|
296
|
+
is_hermes: isHermes,
|
|
297
|
+
is_fabric: isFabric,
|
|
298
|
+
is_dev: isDev,
|
|
299
|
+
environment: environment || (isDev ? 'DEV' : 'PROD'),
|
|
300
|
+
engagement_time_msec: 1000,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export async function trackActiveTelemetryHeartbeat(
|
|
305
|
+
telemetryEnabled = true,
|
|
306
|
+
environment?: string,
|
|
307
|
+
): Promise<void> {
|
|
308
|
+
if (telemetryEnabled === false) {
|
|
309
|
+
isTelemetryEnabled = false;
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
isTelemetryEnabled = true;
|
|
313
|
+
|
|
314
|
+
const url = getCollectUrl();
|
|
315
|
+
if (!url) return;
|
|
316
|
+
|
|
317
|
+
try {
|
|
318
|
+
const settings = await loadSettings();
|
|
319
|
+
const lastPing = settings.telemetryLastPing || 0;
|
|
320
|
+
const now = Date.now();
|
|
321
|
+
|
|
322
|
+
if (now - lastPing < PING_INTERVAL_MS) return;
|
|
323
|
+
|
|
324
|
+
const clientId = await getOrCreateClientId();
|
|
325
|
+
const params = getSystemMetadata(environment);
|
|
326
|
+
|
|
327
|
+
await fetch(url, {
|
|
328
|
+
method: 'POST',
|
|
329
|
+
headers: {'Content-Type': 'application/json'},
|
|
330
|
+
body: JSON.stringify({
|
|
331
|
+
client_id: clientId,
|
|
332
|
+
non_personalized_ads: true,
|
|
333
|
+
events: [{name: 'inspector_active_heartbeat', params}],
|
|
334
|
+
}),
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
saveSettings({...settings, telemetryLastPing: now});
|
|
338
|
+
} catch {
|
|
339
|
+
// silent
|
|
340
|
+
}
|
|
341
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -84,6 +84,11 @@ import {
|
|
|
84
84
|
setCrashModuleEnabled,
|
|
85
85
|
} from './customHooks/crashHandler';
|
|
86
86
|
|
|
87
|
+
import {
|
|
88
|
+
trackActiveTelemetryHeartbeat,
|
|
89
|
+
setTelemetryEnabled,
|
|
90
|
+
} from './helpers/telemetry';
|
|
91
|
+
|
|
87
92
|
import {
|
|
88
93
|
subscribeAnalyticsEvents,
|
|
89
94
|
clearAnalyticsEvents,
|
|
@@ -2170,15 +2175,24 @@ const NetworkInspector = ({
|
|
|
2170
2175
|
|
|
2171
2176
|
const NetworkInspectorWrapper = (props: NetworkInspectorProps) => {
|
|
2172
2177
|
const enabled = props?.enabled ?? true;
|
|
2178
|
+
const telemetry = props?.telemetry ?? true;
|
|
2173
2179
|
|
|
2174
2180
|
useEffect(() => {
|
|
2175
2181
|
if (!enabled) {
|
|
2182
|
+
// When inspector is disabled: hide FAB and kill all telemetry
|
|
2176
2183
|
hideNativeFloatingButton().catch(() => {});
|
|
2184
|
+
setTelemetryEnabled(false);
|
|
2185
|
+
} else if (telemetry) {
|
|
2186
|
+
// Inspector is enabled and telemetry is on — fire heartbeat
|
|
2187
|
+
trackActiveTelemetryHeartbeat(true, props?.environment);
|
|
2188
|
+
} else {
|
|
2189
|
+
// Inspector is enabled but telemetry is explicitly off
|
|
2190
|
+
setTelemetryEnabled(false);
|
|
2177
2191
|
}
|
|
2178
2192
|
return () => {
|
|
2179
2193
|
hideNativeFloatingButton().catch(() => {});
|
|
2180
2194
|
};
|
|
2181
|
-
}, [enabled]);
|
|
2195
|
+
}, [enabled, telemetry, props?.environment]);
|
|
2182
2196
|
|
|
2183
2197
|
// If enabled is false, return null immediately with 0 overhead
|
|
2184
2198
|
if (!enabled) {
|
package/src/types/interfaces.ts
CHANGED
|
@@ -180,12 +180,15 @@ export interface PersistedSettings {
|
|
|
180
180
|
reduxExpandDepth?: number;
|
|
181
181
|
showDuplicateLogs?: boolean;
|
|
182
182
|
showUpdateToast?: boolean;
|
|
183
|
+
telemetryClientId?: string;
|
|
184
|
+
telemetryLastPing?: number;
|
|
183
185
|
}
|
|
184
186
|
|
|
185
187
|
// ─── Inspector component props / context ──────────────────────────────────────
|
|
186
188
|
|
|
187
189
|
export interface NetworkInspectorProps {
|
|
188
190
|
enabled?: boolean;
|
|
191
|
+
telemetry?: boolean;
|
|
189
192
|
storage?: InspectorStorage;
|
|
190
193
|
navigationRef?: any;
|
|
191
194
|
appIcon?: any;
|