react-native-inapp-inspector 1.1.23 → 1.1.25
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/components/AnalyticsEventCard.js +94 -88
- package/dist/commonjs/components/ConsoleLogCard.js +49 -25
- package/dist/commonjs/components/Inspector/AnalyticsFilterModal.d.ts +7 -0
- package/dist/commonjs/components/Inspector/AnalyticsFilterModal.js +1002 -0
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +637 -10
- package/dist/commonjs/components/Inspector/BundleTab.d.ts +1 -1
- package/dist/commonjs/components/Inspector/BundleTab.js +859 -402
- package/dist/commonjs/components/Inspector/InspectorContext.js +6 -1
- package/dist/commonjs/components/Inspector/InspectorHeader.js +13 -5
- package/dist/commonjs/components/Inspector/LogDetail.js +223 -111
- package/dist/commonjs/components/Inspector/MainScreen.js +1 -1
- package/dist/commonjs/components/Inspector/NetworkDetail.js +131 -81
- package/dist/commonjs/components/Inspector/PerformanceTab.js +20 -10
- package/dist/commonjs/components/NetworkIcons.d.ts +14 -0
- package/dist/commonjs/components/NetworkIcons.js +93 -1
- package/dist/commonjs/components/SegmentedTabs.js +31 -22
- package/dist/commonjs/components/TreeNode.js +13 -12
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +6 -2
- package/dist/commonjs/customHooks/bundleAnalyzer.js +552 -114
- package/dist/commonjs/customHooks/consoleLogger.js +83 -45
- package/dist/commonjs/customHooks/networkLogger.js +10 -1
- package/dist/commonjs/customHooks/performanceTracker.d.ts +8 -0
- package/dist/commonjs/customHooks/performanceTracker.js +44 -3
- package/dist/commonjs/decorators/index.d.ts +49 -0
- package/dist/commonjs/decorators/index.js +142 -0
- package/dist/commonjs/helpers/gaAnalyticsRegistry.d.ts +18 -0
- package/dist/commonjs/helpers/gaAnalyticsRegistry.js +174 -0
- package/dist/commonjs/helpers/index.d.ts +7 -4
- package/dist/commonjs/helpers/index.js +102 -64
- package/dist/commonjs/i18n/locales/en.json +53 -4
- package/dist/commonjs/index.d.ts +4 -0
- package/dist/commonjs/index.js +216 -8
- package/dist/commonjs/styles/index.d.ts +4 -1
- package/dist/commonjs/styles/index.js +22 -19
- package/dist/commonjs/types/enums.d.ts +115 -9
- package/dist/commonjs/types/enums.js +103 -2
- package/dist/commonjs/types/interfaces.d.ts +19 -0
- package/dist/esm/components/AnalyticsEventCard.js +95 -89
- package/dist/esm/components/ConsoleLogCard.js +49 -25
- package/dist/esm/components/Inspector/AnalyticsFilterModal.d.ts +7 -0
- package/dist/esm/components/Inspector/AnalyticsFilterModal.js +964 -0
- package/dist/esm/components/Inspector/AnalyticsTab.js +639 -12
- package/dist/esm/components/Inspector/BundleTab.d.ts +1 -1
- package/dist/esm/components/Inspector/BundleTab.js +860 -403
- package/dist/esm/components/Inspector/InspectorContext.js +1 -0
- package/dist/esm/components/Inspector/InspectorHeader.js +14 -6
- package/dist/esm/components/Inspector/LogDetail.js +223 -111
- package/dist/esm/components/Inspector/MainScreen.js +2 -2
- package/dist/esm/components/Inspector/NetworkDetail.js +132 -49
- package/dist/esm/components/Inspector/PerformanceTab.js +20 -10
- package/dist/esm/components/NetworkIcons.d.ts +14 -0
- package/dist/esm/components/NetworkIcons.js +78 -0
- package/dist/esm/components/SegmentedTabs.js +31 -22
- package/dist/esm/components/TreeNode.js +13 -12
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/bundleAnalyzer.d.ts +6 -2
- package/dist/esm/customHooks/bundleAnalyzer.js +549 -114
- package/dist/esm/customHooks/consoleLogger.js +83 -45
- package/dist/esm/customHooks/networkLogger.js +10 -1
- package/dist/esm/customHooks/performanceTracker.d.ts +8 -0
- package/dist/esm/customHooks/performanceTracker.js +38 -1
- package/dist/esm/decorators/index.d.ts +49 -0
- package/dist/esm/decorators/index.js +137 -0
- package/dist/esm/helpers/gaAnalyticsRegistry.d.ts +18 -0
- package/dist/esm/helpers/gaAnalyticsRegistry.js +169 -0
- package/dist/esm/helpers/index.d.ts +7 -4
- package/dist/esm/helpers/index.js +100 -63
- package/dist/esm/i18n/locales/en.json +53 -4
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +190 -8
- package/dist/esm/styles/index.d.ts +4 -1
- package/dist/esm/styles/index.js +22 -19
- package/dist/esm/types/enums.d.ts +115 -9
- package/dist/esm/types/enums.js +102 -3
- package/dist/esm/types/interfaces.d.ts +19 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Clipboard, Platform, ToastAndroid, Alert, NativeModules, Linking } from 'react-native';
|
|
1
|
+
import { Clipboard, Platform, ToastAndroid, Alert, NativeModules, Linking, TurboModuleRegistry, } from 'react-native';
|
|
2
2
|
// Stylesheet
|
|
3
3
|
import { AppColors } from '../styles/AppColors';
|
|
4
4
|
// Constants
|
|
@@ -52,58 +52,83 @@ export const getSize = (data) => {
|
|
|
52
52
|
return '—';
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
|
-
//
|
|
55
|
+
// Safely detect and load clipboard natively without static require() calls that Metro fails on
|
|
56
56
|
const getClipboardModule = () => {
|
|
57
|
+
// 1. Check TurboModuleRegistry (TurboModules / New Architecture)
|
|
57
58
|
try {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
const tmReg = TurboModuleRegistry || globalThis.__turboModuleProxy;
|
|
60
|
+
if (tmReg?.get) {
|
|
61
|
+
const tm = tmReg.get('RNCClipboard') ||
|
|
62
|
+
tmReg.get('NativeClipboard') ||
|
|
63
|
+
tmReg.get('ExpoClipboard');
|
|
64
|
+
if (tm &&
|
|
65
|
+
(typeof tm.setString === 'function' ||
|
|
66
|
+
typeof tm.setStringAsync === 'function')) {
|
|
67
|
+
return tm;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
64
70
|
}
|
|
65
71
|
catch { }
|
|
72
|
+
// 2. Check legacy NativeModules table (Bridge / Old Architecture)
|
|
66
73
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (
|
|
72
|
-
|
|
74
|
+
if (NativeModules?.RNCClipboard &&
|
|
75
|
+
typeof NativeModules.RNCClipboard.setString === 'function') {
|
|
76
|
+
return NativeModules.RNCClipboard;
|
|
77
|
+
}
|
|
78
|
+
if (NativeModules?.ExpoClipboard &&
|
|
79
|
+
typeof NativeModules.ExpoClipboard.setStringAsync === 'function') {
|
|
80
|
+
return NativeModules.ExpoClipboard;
|
|
81
|
+
}
|
|
82
|
+
if (NativeModules?.Clipboard &&
|
|
83
|
+
typeof NativeModules.Clipboard.setString === 'function') {
|
|
84
|
+
return NativeModules.Clipboard;
|
|
85
|
+
}
|
|
73
86
|
}
|
|
74
87
|
catch { }
|
|
88
|
+
// 3. Check legacy React Native core Clipboard
|
|
75
89
|
try {
|
|
76
|
-
if (
|
|
77
|
-
return
|
|
90
|
+
if (Clipboard && typeof Clipboard.setString === 'function') {
|
|
91
|
+
return Clipboard;
|
|
92
|
+
}
|
|
78
93
|
}
|
|
79
94
|
catch { }
|
|
80
|
-
return
|
|
95
|
+
return null;
|
|
81
96
|
};
|
|
82
97
|
export const copyToClipboard = (value, label) => {
|
|
83
98
|
const resolved = typeof value === 'function' ? value() : value;
|
|
84
99
|
const text = typeof resolved === 'string' ? resolved : JSON.stringify(resolved, null, 2);
|
|
85
100
|
const textToCopy = text ?? '';
|
|
101
|
+
let copied = false;
|
|
86
102
|
try {
|
|
87
103
|
const cb = getClipboardModule();
|
|
88
|
-
if (cb
|
|
89
|
-
cb.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
104
|
+
if (cb) {
|
|
105
|
+
if (typeof cb.setStringAsync === 'function') {
|
|
106
|
+
cb.setStringAsync(textToCopy);
|
|
107
|
+
copied = true;
|
|
108
|
+
}
|
|
109
|
+
else if (typeof cb.setString === 'function') {
|
|
110
|
+
cb.setString(textToCopy);
|
|
111
|
+
copied = true;
|
|
112
|
+
}
|
|
93
113
|
}
|
|
94
114
|
}
|
|
95
|
-
catch {
|
|
115
|
+
catch { }
|
|
116
|
+
if (!copied) {
|
|
96
117
|
try {
|
|
97
|
-
|
|
118
|
+
if (typeof navigator !== 'undefined' && navigator?.clipboard?.writeText) {
|
|
119
|
+
navigator.clipboard.writeText(textToCopy);
|
|
120
|
+
copied = true;
|
|
121
|
+
}
|
|
98
122
|
}
|
|
99
123
|
catch { }
|
|
100
124
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
125
|
+
// Visual toast feedback on Android if ToastAndroid exists
|
|
126
|
+
try {
|
|
127
|
+
if (Platform.OS === 'android' && ToastAndroid?.show) {
|
|
128
|
+
ToastAndroid.show(`${label} copied`, ToastAndroid.SHORT);
|
|
129
|
+
}
|
|
106
130
|
}
|
|
131
|
+
catch { }
|
|
107
132
|
};
|
|
108
133
|
export const getPath = (url) => {
|
|
109
134
|
try {
|
|
@@ -445,6 +470,10 @@ export const parseStackLine = (rawLine, isOrigin = false) => {
|
|
|
445
470
|
functionName = parenMatch[1].trim() || '<anonymous>';
|
|
446
471
|
locationPart = parenMatch[2].trim();
|
|
447
472
|
}
|
|
473
|
+
// Clean Babel/Hermes artifacts in function names like ?anon_0_, _callee$, etc.
|
|
474
|
+
if (functionName.startsWith('?anon_') || functionName === '?') {
|
|
475
|
+
functionName = 'anonymous';
|
|
476
|
+
}
|
|
448
477
|
// Remove "address at " prefix if present in Hermes
|
|
449
478
|
locationPart = locationPart.replace(/^address at /, '');
|
|
450
479
|
// Extract file, line, and col from locationPart (e.g. "path/to/file.tsx:42:15" or "http://...:42:15")
|
|
@@ -472,20 +501,56 @@ export const parseStackLine = (rawLine, isOrigin = false) => {
|
|
|
472
501
|
const fileExt = ext === 'tsx' || ext === 'jsx' || ext === 'ts' || ext === 'js'
|
|
473
502
|
? ext
|
|
474
503
|
: 'other';
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
(
|
|
504
|
+
const isNative = locationPart === 'native' || cleanPath === 'native';
|
|
505
|
+
const isInternalBytecode = cleanPath.includes('InternalBytecode') ||
|
|
506
|
+
cleanPath.includes('metro-runtime') ||
|
|
507
|
+
cleanPath.includes('regenerator-runtime') ||
|
|
508
|
+
functionName === 'tryCallOne' ||
|
|
509
|
+
functionName === 'asyncGeneratorStep' ||
|
|
510
|
+
functionName === '_next' ||
|
|
511
|
+
(functionName === 'next' && isNative);
|
|
512
|
+
const isDependency = cleanPath.includes('node_modules') ||
|
|
513
|
+
cleanPath.includes('react-native/Libraries') ||
|
|
514
|
+
(cleanPath.includes('react-native-inapp-inspector') && !cleanPath.includes('/example/'));
|
|
515
|
+
const isUserCode = !isNative &&
|
|
516
|
+
!isInternalBytecode &&
|
|
517
|
+
!isDependency &&
|
|
518
|
+
(fileExt === 'tsx' || fileExt === 'jsx' || fileExt === 'ts' || fileExt === 'js' || !fileName.includes('.bundle'));
|
|
519
|
+
const frameType = isUserCode
|
|
520
|
+
? 'app'
|
|
521
|
+
: isDependency
|
|
522
|
+
? 'dependency'
|
|
523
|
+
: isNative
|
|
524
|
+
? 'native'
|
|
525
|
+
: 'runtime';
|
|
526
|
+
const isRuntimeNoise = isInternalBytecode || isNative || functionName === 'asyncGeneratorStep' || functionName === '_next';
|
|
527
|
+
// Format clean relative project path
|
|
528
|
+
let relativePath = cleanPath;
|
|
529
|
+
if (relativePath.includes('/example/')) {
|
|
530
|
+
relativePath = relativePath.substring(relativePath.indexOf('/example/') + 9);
|
|
531
|
+
}
|
|
532
|
+
else if (relativePath.includes('/src/')) {
|
|
533
|
+
relativePath = relativePath.substring(relativePath.indexOf('/src/') + 1);
|
|
534
|
+
}
|
|
535
|
+
else if (relativePath.includes('/node_modules/')) {
|
|
536
|
+
relativePath = relativePath.substring(relativePath.indexOf('/node_modules/') + 14);
|
|
537
|
+
}
|
|
538
|
+
const copyableLocation = lineNumber
|
|
539
|
+
? `${fileName}:${lineNumber}${columnNumber ? `:${columnNumber}` : ''}`
|
|
540
|
+
: fileName;
|
|
479
541
|
return {
|
|
480
542
|
raw: rawLine,
|
|
481
543
|
functionName,
|
|
482
544
|
fileName,
|
|
483
|
-
fullPath:
|
|
545
|
+
fullPath: relativePath,
|
|
484
546
|
fileExt,
|
|
547
|
+
frameType,
|
|
485
548
|
isUserCode,
|
|
549
|
+
isRuntimeNoise,
|
|
486
550
|
lineNumber,
|
|
487
551
|
columnNumber,
|
|
488
552
|
isOrigin,
|
|
553
|
+
copyableLocation,
|
|
489
554
|
};
|
|
490
555
|
};
|
|
491
556
|
// ─── Analytics Helpers ────────────────────────────────────────────────────────
|
|
@@ -507,35 +572,7 @@ export const getEventColor = (name) => {
|
|
|
507
572
|
}
|
|
508
573
|
return ANALYTICS_EVENT_PALETTE[Math.abs(hash) % ANALYTICS_EVENT_PALETTE.length];
|
|
509
574
|
};
|
|
510
|
-
export
|
|
511
|
-
if (!name)
|
|
512
|
-
return 'custom';
|
|
513
|
-
const lowercaseName = name.toLowerCase();
|
|
514
|
-
if (lowercaseName === 'screen_view' || lowercaseName === 'page_view') {
|
|
515
|
-
return 'page_view';
|
|
516
|
-
}
|
|
517
|
-
// Ecommerce events
|
|
518
|
-
const ecommerceEvents = [
|
|
519
|
-
'purchase', 'add_to_cart', 'begin_checkout', 'view_item',
|
|
520
|
-
'select_item', 'remove_from_cart', 'view_cart',
|
|
521
|
-
'add_shipping_info', 'add_payment_info', 'refund',
|
|
522
|
-
'view_item_list', 'select_promotion', 'view_promotion'
|
|
523
|
-
];
|
|
524
|
-
if (ecommerceEvents.includes(lowercaseName)) {
|
|
525
|
-
return 'ecommerce';
|
|
526
|
-
}
|
|
527
|
-
// Firebase System Auto-events
|
|
528
|
-
const systemEvents = [
|
|
529
|
-
'first_open', 'session_start', 'user_engagement',
|
|
530
|
-
'app_clear_data', 'app_exception', 'app_update', 'os_update',
|
|
531
|
-
'notification_receive', 'notification_open', 'notification_dismiss',
|
|
532
|
-
'screen_active', 'screen_inactive'
|
|
533
|
-
];
|
|
534
|
-
if (systemEvents.includes(lowercaseName) || lowercaseName.startsWith('firebase_') || lowercaseName.startsWith('_')) {
|
|
535
|
-
return 'system';
|
|
536
|
-
}
|
|
537
|
-
return 'custom';
|
|
538
|
-
};
|
|
575
|
+
export { getEventCategory, registerGAPlugin, } from './gaAnalyticsRegistry';
|
|
539
576
|
export const getCategoryColors = (category) => {
|
|
540
577
|
switch (category) {
|
|
541
578
|
case 'page_view':
|
|
@@ -211,7 +211,29 @@
|
|
|
211
211
|
"filterWarn": "Warn",
|
|
212
212
|
"filterError": "Error",
|
|
213
213
|
"filterUserLog": "User Log",
|
|
214
|
-
"filterAnalytics": "Analytics"
|
|
214
|
+
"filterAnalytics": "Analytics",
|
|
215
|
+
"tabOutput": "Output",
|
|
216
|
+
"tabArgs": "Args ({{count}})",
|
|
217
|
+
"tabStack": "Stack Trace",
|
|
218
|
+
"tabMetadata": "Metadata",
|
|
219
|
+
"callStack": "Call Stack ({{count}} frames)",
|
|
220
|
+
"errorStack": "Error Exception Stack ({{count}} frames)",
|
|
221
|
+
"callOriginStack": "Call Origin Stack",
|
|
222
|
+
"errorThrownStack": "Error Thrown Stack",
|
|
223
|
+
"appCodeScope": "🎯 App Code ({{count}})",
|
|
224
|
+
"allFramesScope": "📜 All Frames ({{count}})",
|
|
225
|
+
"cardsView": "Cards",
|
|
226
|
+
"rawTraceView": "Raw",
|
|
227
|
+
"noStackAvailable": "No call stack frames found matching the active filter.",
|
|
228
|
+
"originBadge": "#1 ORIGIN",
|
|
229
|
+
"appCodeBadge": "App Code",
|
|
230
|
+
"dependencyBadge": "Dependency",
|
|
231
|
+
"nativeBadge": "Native",
|
|
232
|
+
"hermesVmBadge": "Hermes VM",
|
|
233
|
+
"fullStackTrace": "Full Stack Trace",
|
|
234
|
+
"lineCol": "Line {{line}}, Col {{col}}",
|
|
235
|
+
"lineColShort": "L{{line}}:C{{col}}",
|
|
236
|
+
"searchInLogDetails": "Search in log details..."
|
|
215
237
|
},
|
|
216
238
|
"analytics": {
|
|
217
239
|
"title": "Analytics",
|
|
@@ -355,6 +377,8 @@
|
|
|
355
377
|
"heroTitle": "Bundle & Asset Architecture",
|
|
356
378
|
"heroSubtitle": "Real-time size breakdown across all assets, code, and dependencies",
|
|
357
379
|
"heroSubtitleLive": "Live analysis of {{scriptUrl}}",
|
|
380
|
+
"liveAnalysisUnavailable": "Live bundle analysis unavailable",
|
|
381
|
+
"liveAnalysisUnavailableSub": "Could not reach the Metro dev server, so values are estimates. Make sure the app runs in development via `npx react-native start` and the Inspector can reach your Metro port (8081, 8082, ...).",
|
|
358
382
|
"bundleOverviewJson": "Bundle Overview JSON",
|
|
359
383
|
"devBundleSize": "DEV BUNDLE SIZE",
|
|
360
384
|
"devBundleHint": "{{kb}} KB • {{modules}} modules",
|
|
@@ -396,11 +420,36 @@
|
|
|
396
420
|
"catTsDesc": "App screen components, hooks, and business logic",
|
|
397
421
|
"catJsonTitle": "JSON Data & Localizations",
|
|
398
422
|
"catJsonDesc": "i18n translation dictionaries and static configs",
|
|
399
|
-
"
|
|
400
|
-
"totalBundleAssets": "TOTAL BUNDLE ASSETS",
|
|
423
|
+
"totalBundleAssets": "TOTAL HOST PROJECT FILES",
|
|
401
424
|
"totalBundleValue": "{{kb}} KB (~{{mb}} MB)",
|
|
402
|
-
"totalFormula": "Sum: {{images}} KB + {{js}} KB + {{fonts}} KB + {{ts}} KB + {{json}} KB = {{total}} KB ({{count}} items
|
|
425
|
+
"totalFormula": "Sum of host source files: {{images}} KB + {{js}} KB + {{fonts}} KB + {{ts}} KB + {{json}} KB = {{total}} KB ({{count}} items)",
|
|
426
|
+
"prodIosApp": "iOS App (.ipa)",
|
|
427
|
+
"prodAndroidAab": "Android AAB (.aab)",
|
|
428
|
+
"prodAndroidApk": "Universal APK (.apk)",
|
|
429
|
+
"prodHeroTitleIos": "iOS Production Binary Footprint",
|
|
430
|
+
"prodHeroTitleAab": "Google Play App Bundle (.aab)",
|
|
431
|
+
"prodHeroTitleApk": "Universal Standalone APK (.apk)",
|
|
432
|
+
"prodHeroSubIos": "App Store install & over-the-air cellular download estimates",
|
|
433
|
+
"prodHeroSubAab": "Optimized per-device dynamic delivery split APK architecture",
|
|
434
|
+
"prodHeroSubApk": "Multi-ABI universal install archive for sideloading & direct distribution",
|
|
435
|
+
"prodInstallSize": "INSTALL SIZE",
|
|
436
|
+
"prodInstallHint": "On-device uncompressed footprint",
|
|
437
|
+
"prodDownloadSize": "DOWNLOAD SIZE",
|
|
438
|
+
"prodDownloadHint": "Store network transfer payload",
|
|
439
|
+
"prodCompression": "COMPRESSION",
|
|
440
|
+
"prodCompressionHint": "Bytecode & asset ratio",
|
|
441
|
+
"prodFormatArch": "FORMAT ARCHITECTURE",
|
|
442
|
+
"prodFormatHintIos": "Apple ARM64 runtime",
|
|
443
|
+
"prodFormatHintAab": "Dynamic Google Play delivery",
|
|
444
|
+
"prodFormatHintApk": "Sideload universal package",
|
|
445
|
+
"prodArchTitle": "Binary Component Architecture",
|
|
446
|
+
"prodArchSub": "Compiled native libraries, runtime bytecodes, assets, and signature blocks",
|
|
447
|
+
"prodTotalIos": "TOTAL IOS APP BINARY",
|
|
448
|
+
"prodTotalAab": "TOTAL ANDROID AAB BUNDLE",
|
|
449
|
+
"prodTotalApk": "TOTAL UNIVERSAL APK",
|
|
450
|
+
"prodTotalFormula": "From {{devKb}} KB (~{{devMb}} MB • {{count}} total assets) dev source bundle → {{installMb}} MB optimized native binary ({{pct}}% bytecode/asset compression).",
|
|
403
451
|
"tabOverview": "Overview",
|
|
452
|
+
"tabProduction": "Production ({{count}})",
|
|
404
453
|
"tabFiles": "Files ({{count}})",
|
|
405
454
|
"tabPackages": "Packages ({{count}})",
|
|
406
455
|
"tabMedia": "Media ({{count}})",
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -7,3 +7,7 @@ export { setupConsoleLogger, clearConsoleLogs, subscribeConsoleLogs, } from './c
|
|
|
7
7
|
export { setupAnalyticsLogger, logAnalyticsEvent, subscribeAnalyticsEvents, clearAnalyticsEvents, getCurrentUserProperties, getCurrentUserId, getDefaultEventParameters, getCollectionEnabled, } from './customHooks/analyticsLogger';
|
|
8
8
|
export { default as ErrorBoundary } from './components/ErrorBoundary';
|
|
9
9
|
export { connectReduxStore, inspectorReduxMiddleware, getReduxState, subscribeReduxState, getActionHistory, clearActionHistory, getLastActionForReducer, } from './customHooks/reduxLogger';
|
|
10
|
+
export { getEventCategory, registerGAPlugin, type GAPlugin, } from './helpers/gaAnalyticsRegistry';
|
|
11
|
+
export { usePerformanceTracker, logPerformanceEvent, clearPerformanceEvents, subscribePerformanceEvents, getPerformanceEvents, } from './customHooks/performanceTracker';
|
|
12
|
+
export { InspectLog, InspectTrackTime, InspectCatch, type InspectLogOptions, } from './decorators';
|
|
13
|
+
export { ActiveTab, Method, StatusFilter, SortOrder, LocalFilter, ModalAnimationType, SettingsPage, SettingsSubTab, LogFilter, ConsoleLogType, AnalyticsEventSource, GAEventCategory, StackFrameType, DiffResultType, BundleSubTab, PerformanceSubTab, } from './types';
|
package/dist/esm/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import ErrorBoundary from './components/ErrorBoundary';
|
|
|
8
8
|
import MainScreen from './components/Inspector/MainScreen';
|
|
9
9
|
import { InspectorContext, animateNextLayout, } from './components/Inspector/InspectorContext';
|
|
10
10
|
// Helpers
|
|
11
|
-
import { formatDisplayUrl, getNavigationInfo, deduplicateLogs, getDomainColor, } from './helpers';
|
|
11
|
+
import { formatDisplayUrl, getNavigationInfo, deduplicateLogs, getDomainColor, getEventCategory, } from './helpers';
|
|
12
12
|
// #5 — settings persistence
|
|
13
13
|
import { loadSettings, saveSettings, setCustomStorage, clearPersistedSettings, } from './helpers/settingsStore';
|
|
14
14
|
// Network
|
|
@@ -332,7 +332,67 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
332
332
|
}, []);
|
|
333
333
|
const [selectedEvent, setSelectedEvent] = useState(null);
|
|
334
334
|
const [analyticsSearch, setAnalyticsSearch] = useState('');
|
|
335
|
-
const [
|
|
335
|
+
const [analyticsFilters, setAnalyticsFilters] = useState({
|
|
336
|
+
categories: new Set(['all']),
|
|
337
|
+
screens: new Set(),
|
|
338
|
+
sources: new Set(['all']),
|
|
339
|
+
userTypes: new Set(['all']),
|
|
340
|
+
timeWindow: 'all',
|
|
341
|
+
payloadComplexity: 'all',
|
|
342
|
+
hasRevenue: false,
|
|
343
|
+
hasItems: false,
|
|
344
|
+
hasUserProps: false,
|
|
345
|
+
hasParams: false,
|
|
346
|
+
onlyDuplicates: false,
|
|
347
|
+
onlyConversions: false,
|
|
348
|
+
sortBy: 'time_desc',
|
|
349
|
+
});
|
|
350
|
+
const isAnalyticsFilterApplied = useMemo(() => {
|
|
351
|
+
if (analyticsFilters.categories.size > 0 && !analyticsFilters.categories.has('all'))
|
|
352
|
+
return true;
|
|
353
|
+
if (analyticsFilters.screens.size > 0)
|
|
354
|
+
return true;
|
|
355
|
+
if (analyticsFilters.sources.size > 0 && !analyticsFilters.sources.has('all'))
|
|
356
|
+
return true;
|
|
357
|
+
if (analyticsFilters.userTypes.size > 0 && !analyticsFilters.userTypes.has('all'))
|
|
358
|
+
return true;
|
|
359
|
+
if (analyticsFilters.timeWindow !== 'all')
|
|
360
|
+
return true;
|
|
361
|
+
if (analyticsFilters.payloadComplexity !== 'all')
|
|
362
|
+
return true;
|
|
363
|
+
if (analyticsFilters.hasRevenue)
|
|
364
|
+
return true;
|
|
365
|
+
if (analyticsFilters.hasItems)
|
|
366
|
+
return true;
|
|
367
|
+
if (analyticsFilters.hasUserProps)
|
|
368
|
+
return true;
|
|
369
|
+
if (analyticsFilters.hasParams)
|
|
370
|
+
return true;
|
|
371
|
+
if (analyticsFilters.onlyDuplicates)
|
|
372
|
+
return true;
|
|
373
|
+
if (analyticsFilters.onlyConversions)
|
|
374
|
+
return true;
|
|
375
|
+
if (analyticsFilters.sortBy !== 'time_desc')
|
|
376
|
+
return true;
|
|
377
|
+
return false;
|
|
378
|
+
}, [analyticsFilters]);
|
|
379
|
+
const resetAnalyticsFilters = useCallback(() => {
|
|
380
|
+
setAnalyticsFilters({
|
|
381
|
+
categories: new Set(['all']),
|
|
382
|
+
screens: new Set(),
|
|
383
|
+
sources: new Set(['all']),
|
|
384
|
+
userTypes: new Set(['all']),
|
|
385
|
+
timeWindow: 'all',
|
|
386
|
+
payloadComplexity: 'all',
|
|
387
|
+
hasRevenue: false,
|
|
388
|
+
hasItems: false,
|
|
389
|
+
hasUserProps: false,
|
|
390
|
+
hasParams: false,
|
|
391
|
+
onlyDuplicates: false,
|
|
392
|
+
onlyConversions: false,
|
|
393
|
+
sortBy: 'time_desc',
|
|
394
|
+
});
|
|
395
|
+
}, []);
|
|
336
396
|
const [isAnalyticsLayoutReady, setIsAnalyticsLayoutReady] = useState(false);
|
|
337
397
|
const [analyticsHeaderExpanded, setAnalyticsHeaderExpanded] = useState(false);
|
|
338
398
|
const [newEventIds, setNewEventIds] = useState(new Set());
|
|
@@ -866,15 +926,110 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
866
926
|
const prevResponseData = prevSameRequest ? prevSameRequest.response : null;
|
|
867
927
|
const filteredAnalyticsEvents = useMemo(() => {
|
|
868
928
|
let events = analyticsEvents;
|
|
869
|
-
|
|
870
|
-
events = events.filter(e => e.name !== 'screen_view');
|
|
871
|
-
}
|
|
929
|
+
// Search query filter
|
|
872
930
|
if (analyticsSearch) {
|
|
873
931
|
const s = analyticsSearch.toLowerCase();
|
|
874
932
|
events = events.filter(e => e.name.toLowerCase().includes(s) ||
|
|
875
|
-
JSON.stringify(e.params).toLowerCase().includes(s) ||
|
|
933
|
+
JSON.stringify(e.params || {}).toLowerCase().includes(s) ||
|
|
934
|
+
(e.screenName ?? '').toLowerCase().includes(s) ||
|
|
876
935
|
(e.pageTitle ?? '').toLowerCase().includes(s));
|
|
877
936
|
}
|
|
937
|
+
// Category filter
|
|
938
|
+
if (analyticsFilters.categories.size > 0 && !analyticsFilters.categories.has('all')) {
|
|
939
|
+
events = events.filter(e => {
|
|
940
|
+
const cat = getEventCategory(e.name);
|
|
941
|
+
return analyticsFilters.categories.has(cat);
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
// Time window filter
|
|
945
|
+
if (analyticsFilters.timeWindow !== 'all') {
|
|
946
|
+
const now = Date.now();
|
|
947
|
+
const cutoff = analyticsFilters.timeWindow === '1m'
|
|
948
|
+
? now - 60 * 1000
|
|
949
|
+
: analyticsFilters.timeWindow === '5m'
|
|
950
|
+
? now - 5 * 60 * 1000
|
|
951
|
+
: analyticsFilters.timeWindow === '15m'
|
|
952
|
+
? now - 15 * 60 * 1000
|
|
953
|
+
: now - 60 * 60 * 1000;
|
|
954
|
+
events = events.filter(e => e.timestamp >= cutoff);
|
|
955
|
+
}
|
|
956
|
+
// Source filter
|
|
957
|
+
if (analyticsFilters.sources.size > 0 && !analyticsFilters.sources.has('all')) {
|
|
958
|
+
events = events.filter(e => analyticsFilters.sources.has(e.source || 'manual'));
|
|
959
|
+
}
|
|
960
|
+
// User identification filter
|
|
961
|
+
if (analyticsFilters.userTypes.size > 0 && !analyticsFilters.userTypes.has('all')) {
|
|
962
|
+
events = events.filter(e => {
|
|
963
|
+
const isIdentified = Boolean(e.userId && e.userId.trim() !== '');
|
|
964
|
+
if (analyticsFilters.userTypes.has('identified') && isIdentified)
|
|
965
|
+
return true;
|
|
966
|
+
if (analyticsFilters.userTypes.has('anonymous') && !isIdentified)
|
|
967
|
+
return true;
|
|
968
|
+
return false;
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
// Payload complexity filter
|
|
972
|
+
if (analyticsFilters.payloadComplexity !== 'all') {
|
|
973
|
+
events = events.filter(e => {
|
|
974
|
+
const count = e.params ? Object.keys(e.params).length : 0;
|
|
975
|
+
if (analyticsFilters.payloadComplexity === 'none')
|
|
976
|
+
return count === 0;
|
|
977
|
+
if (analyticsFilters.payloadComplexity === 'simple')
|
|
978
|
+
return count >= 1 && count <= 5;
|
|
979
|
+
if (analyticsFilters.payloadComplexity === 'heavy')
|
|
980
|
+
return count > 5;
|
|
981
|
+
return true;
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
// Conversion / Goal events filter
|
|
985
|
+
if (analyticsFilters.onlyConversions) {
|
|
986
|
+
const CONVERSION_PATTERNS = [
|
|
987
|
+
'purchase',
|
|
988
|
+
'item_purchase',
|
|
989
|
+
'ecommerce_purchase',
|
|
990
|
+
'sign_up',
|
|
991
|
+
'login',
|
|
992
|
+
'lead',
|
|
993
|
+
'generate_lead',
|
|
994
|
+
'tutorial_complete',
|
|
995
|
+
'add_payment_info',
|
|
996
|
+
'begin_checkout',
|
|
997
|
+
'spend_virtual_currency',
|
|
998
|
+
];
|
|
999
|
+
events = events.filter(e => CONVERSION_PATTERNS.some(pat => e.name.toLowerCase().includes(pat)));
|
|
1000
|
+
}
|
|
1001
|
+
// Screen filter
|
|
1002
|
+
if (analyticsFilters.screens.size > 0) {
|
|
1003
|
+
events = events.filter(e => {
|
|
1004
|
+
const scr = e.screenName ||
|
|
1005
|
+
e.params?.firebase_screen ||
|
|
1006
|
+
e.params?.screen_name ||
|
|
1007
|
+
e.params?.firebase_screen_class ||
|
|
1008
|
+
e.screenClass ||
|
|
1009
|
+
'';
|
|
1010
|
+
return analyticsFilters.screens.has(scr);
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
// Has Revenue filter
|
|
1014
|
+
if (analyticsFilters.hasRevenue) {
|
|
1015
|
+
events = events.filter(e => {
|
|
1016
|
+
const val = e.params?.value ?? e.params?.price;
|
|
1017
|
+
return val !== undefined && val !== null && Number(val) > 0;
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
// Has Items filter
|
|
1021
|
+
if (analyticsFilters.hasItems) {
|
|
1022
|
+
events = events.filter(e => Array.isArray(e.params?.items) && e.params.items.length > 0);
|
|
1023
|
+
}
|
|
1024
|
+
// Has User Props filter
|
|
1025
|
+
if (analyticsFilters.hasUserProps) {
|
|
1026
|
+
events = events.filter(e => e.userProperties && Object.keys(e.userProperties).length > 0);
|
|
1027
|
+
}
|
|
1028
|
+
// Has Params filter
|
|
1029
|
+
if (analyticsFilters.hasParams) {
|
|
1030
|
+
events = events.filter(e => e.params && Object.keys(e.params).length > 0);
|
|
1031
|
+
}
|
|
1032
|
+
// Deduplication
|
|
878
1033
|
const deduplicatedEvents = [];
|
|
879
1034
|
for (const e of events) {
|
|
880
1035
|
if (deduplicatedEvents.length === 0) {
|
|
@@ -894,8 +1049,27 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
894
1049
|
deduplicatedEvents.push({ ...e, count: 1 });
|
|
895
1050
|
}
|
|
896
1051
|
}
|
|
897
|
-
|
|
898
|
-
|
|
1052
|
+
let result = deduplicatedEvents;
|
|
1053
|
+
// Only duplicates filter
|
|
1054
|
+
if (analyticsFilters.onlyDuplicates) {
|
|
1055
|
+
result = result.filter(e => (e.count || 1) > 1);
|
|
1056
|
+
}
|
|
1057
|
+
// Sorting
|
|
1058
|
+
if (analyticsFilters.sortBy === 'time_asc') {
|
|
1059
|
+
result = [...result].sort((a, b) => a.timestamp - b.timestamp);
|
|
1060
|
+
}
|
|
1061
|
+
else if (analyticsFilters.sortBy === 'revenue_desc') {
|
|
1062
|
+
result = [...result].sort((a, b) => {
|
|
1063
|
+
const valA = Number(a.params?.value ?? a.params?.price ?? 0);
|
|
1064
|
+
const valB = Number(b.params?.value ?? b.params?.price ?? 0);
|
|
1065
|
+
return valB - valA;
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
else if (analyticsFilters.sortBy === 'count_desc') {
|
|
1069
|
+
result = [...result].sort((a, b) => (b.count || 1) - (a.count || 1));
|
|
1070
|
+
}
|
|
1071
|
+
return result;
|
|
1072
|
+
}, [analyticsEvents, analyticsSearch, analyticsFilters]);
|
|
899
1073
|
const filteredConsoleLogs = useMemo(() => {
|
|
900
1074
|
let result = visibleConsoleLogs;
|
|
901
1075
|
// Filters check
|
|
@@ -1194,6 +1368,10 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
1194
1368
|
filteredAnalyticsEvents,
|
|
1195
1369
|
analyticsSearch,
|
|
1196
1370
|
setAnalyticsSearch,
|
|
1371
|
+
analyticsFilters,
|
|
1372
|
+
setAnalyticsFilters,
|
|
1373
|
+
isAnalyticsFilterApplied,
|
|
1374
|
+
resetAnalyticsFilters,
|
|
1197
1375
|
newEventIds,
|
|
1198
1376
|
isAnalyticsLayoutReady,
|
|
1199
1377
|
setIsAnalyticsLayoutReady,
|
|
@@ -1258,3 +1436,7 @@ export { setupConsoleLogger, clearConsoleLogs, subscribeConsoleLogs, } from './c
|
|
|
1258
1436
|
export { setupAnalyticsLogger, logAnalyticsEvent, subscribeAnalyticsEvents, clearAnalyticsEvents, getCurrentUserProperties, getCurrentUserId, getDefaultEventParameters, getCollectionEnabled, } from './customHooks/analyticsLogger';
|
|
1259
1437
|
export { default as ErrorBoundary } from './components/ErrorBoundary';
|
|
1260
1438
|
export { connectReduxStore, inspectorReduxMiddleware, getReduxState, subscribeReduxState, getActionHistory, clearActionHistory, getLastActionForReducer, } from './customHooks/reduxLogger';
|
|
1439
|
+
export { getEventCategory, registerGAPlugin, } from './helpers/gaAnalyticsRegistry';
|
|
1440
|
+
export { usePerformanceTracker, logPerformanceEvent, clearPerformanceEvents, subscribePerformanceEvents, getPerformanceEvents, } from './customHooks/performanceTracker';
|
|
1441
|
+
export { InspectLog, InspectTrackTime, InspectCatch, } from './decorators';
|
|
1442
|
+
export { ActiveTab, Method, StatusFilter, SortOrder, LocalFilter, ModalAnimationType, SettingsPage, SettingsSubTab, LogFilter, ConsoleLogType, AnalyticsEventSource, GAEventCategory, StackFrameType, DiffResultType, BundleSubTab, PerformanceSubTab, } from './types';
|
|
@@ -641,6 +641,10 @@ export declare const getRawStyles: (colors: typeof AppColors) => {
|
|
|
641
641
|
fontSize: number;
|
|
642
642
|
color: string;
|
|
643
643
|
letterSpacing: number;
|
|
644
|
+
backgroundColor: string;
|
|
645
|
+
paddingHorizontal: number;
|
|
646
|
+
paddingVertical: number;
|
|
647
|
+
borderRadius: number;
|
|
644
648
|
};
|
|
645
649
|
slugText: {
|
|
646
650
|
fontFamily: string;
|
|
@@ -1457,7 +1461,6 @@ export declare const getRawStyles: (colors: typeof AppColors) => {
|
|
|
1457
1461
|
flexDirection: string;
|
|
1458
1462
|
justifyContent: string;
|
|
1459
1463
|
alignItems: string;
|
|
1460
|
-
marginBottom: number;
|
|
1461
1464
|
};
|
|
1462
1465
|
analyticsHeaderTitle: {
|
|
1463
1466
|
fontFamily: string;
|