react-native-inapp-inspector 1.0.0
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/LICENSE +21 -0
- package/README.md +97 -0
- package/dist/commonjs/components/AnalyticsDetail.d.ts +6 -0
- package/dist/commonjs/components/AnalyticsDetail.js +558 -0
- package/dist/commonjs/components/AnalyticsEventCard.d.ts +18 -0
- package/dist/commonjs/components/AnalyticsEventCard.js +327 -0
- package/dist/commonjs/components/AnalyticsGraph.d.ts +8 -0
- package/dist/commonjs/components/AnalyticsGraph.js +416 -0
- package/dist/commonjs/components/CodeSnippet.d.ts +8 -0
- package/dist/commonjs/components/CodeSnippet.js +427 -0
- package/dist/commonjs/components/ConsoleLogCard.d.ts +10 -0
- package/dist/commonjs/components/ConsoleLogCard.js +401 -0
- package/dist/commonjs/components/CopyButton.d.ts +4 -0
- package/dist/commonjs/components/CopyButton.js +69 -0
- package/dist/commonjs/components/DiffViewer.d.ts +7 -0
- package/dist/commonjs/components/DiffViewer.js +86 -0
- package/dist/commonjs/components/DomainHeader.d.ts +18 -0
- package/dist/commonjs/components/DomainHeader.js +136 -0
- package/dist/commonjs/components/EmptyState.d.ts +5 -0
- package/dist/commonjs/components/EmptyState.js +40 -0
- package/dist/commonjs/components/HeadersSection.d.ts +4 -0
- package/dist/commonjs/components/HeadersSection.js +155 -0
- package/dist/commonjs/components/HighlightText.d.ts +3 -0
- package/dist/commonjs/components/HighlightText.js +57 -0
- package/dist/commonjs/components/JsonViewer.d.ts +7 -0
- package/dist/commonjs/components/JsonViewer.js +19 -0
- package/dist/commonjs/components/LogCard.d.ts +4 -0
- package/dist/commonjs/components/LogCard.js +179 -0
- package/dist/commonjs/components/MetaAccordion.d.ts +4 -0
- package/dist/commonjs/components/MetaAccordion.js +113 -0
- package/dist/commonjs/components/MiniBarChart.d.ts +7 -0
- package/dist/commonjs/components/MiniBarChart.js +56 -0
- package/dist/commonjs/components/MiniLineChart.d.ts +6 -0
- package/dist/commonjs/components/MiniLineChart.js +58 -0
- package/dist/commonjs/components/NetworkIcons.d.ts +31 -0
- package/dist/commonjs/components/NetworkIcons.js +245 -0
- package/dist/commonjs/components/SectionHeader.d.ts +4 -0
- package/dist/commonjs/components/SectionHeader.js +87 -0
- package/dist/commonjs/components/SourcePageCard.d.ts +4 -0
- package/dist/commonjs/components/SourcePageCard.js +132 -0
- package/dist/commonjs/components/TouchableScale.d.ts +9 -0
- package/dist/commonjs/components/TouchableScale.js +44 -0
- package/dist/commonjs/components/TreeNode.d.ts +4 -0
- package/dist/commonjs/components/TreeNode.js +140 -0
- package/dist/commonjs/constants/index.d.ts +7 -0
- package/dist/commonjs/constants/index.js +35 -0
- package/dist/commonjs/customHooks/analyticsLogger.d.ts +21 -0
- package/dist/commonjs/customHooks/analyticsLogger.js +160 -0
- package/dist/commonjs/customHooks/consoleLogger.d.ts +5 -0
- package/dist/commonjs/customHooks/consoleLogger.js +141 -0
- package/dist/commonjs/customHooks/logFilters.d.ts +5 -0
- package/dist/commonjs/customHooks/logFilters.js +34 -0
- package/dist/commonjs/customHooks/networkLogger.d.ts +20 -0
- package/dist/commonjs/customHooks/networkLogger.js +272 -0
- package/dist/commonjs/customHooks/useAccordion.d.ts +17 -0
- package/dist/commonjs/customHooks/useAccordion.js +48 -0
- package/dist/commonjs/customHooks/webViewLogger.d.ts +22 -0
- package/dist/commonjs/customHooks/webViewLogger.js +412 -0
- package/dist/commonjs/helpers/index.d.ts +20 -0
- package/dist/commonjs/helpers/index.js +229 -0
- package/dist/commonjs/index.d.ts +7 -0
- package/dist/commonjs/index.js +2668 -0
- package/dist/commonjs/styles/AppColors.d.ts +27 -0
- package/dist/commonjs/styles/AppColors.js +30 -0
- package/dist/commonjs/styles/AppFonts.d.ts +7 -0
- package/dist/commonjs/styles/AppFonts.js +10 -0
- package/dist/commonjs/styles/index.d.ts +1488 -0
- package/dist/commonjs/styles/index.js +1357 -0
- package/dist/commonjs/types/index.d.ts +127 -0
- package/dist/commonjs/types/index.js +2 -0
- package/dist/esm/components/AnalyticsDetail.d.ts +6 -0
- package/dist/esm/components/AnalyticsDetail.js +520 -0
- package/dist/esm/components/AnalyticsEventCard.d.ts +18 -0
- package/dist/esm/components/AnalyticsEventCard.js +288 -0
- package/dist/esm/components/AnalyticsGraph.d.ts +8 -0
- package/dist/esm/components/AnalyticsGraph.js +378 -0
- package/dist/esm/components/CodeSnippet.d.ts +8 -0
- package/dist/esm/components/CodeSnippet.js +392 -0
- package/dist/esm/components/ConsoleLogCard.d.ts +10 -0
- package/dist/esm/components/ConsoleLogCard.js +362 -0
- package/dist/esm/components/CopyButton.d.ts +4 -0
- package/dist/esm/components/CopyButton.js +31 -0
- package/dist/esm/components/DiffViewer.d.ts +7 -0
- package/dist/esm/components/DiffViewer.js +48 -0
- package/dist/esm/components/DomainHeader.d.ts +18 -0
- package/dist/esm/components/DomainHeader.js +98 -0
- package/dist/esm/components/EmptyState.d.ts +5 -0
- package/dist/esm/components/EmptyState.js +35 -0
- package/dist/esm/components/HeadersSection.d.ts +4 -0
- package/dist/esm/components/HeadersSection.js +117 -0
- package/dist/esm/components/HighlightText.d.ts +3 -0
- package/dist/esm/components/HighlightText.js +52 -0
- package/dist/esm/components/JsonViewer.d.ts +7 -0
- package/dist/esm/components/JsonViewer.js +14 -0
- package/dist/esm/components/LogCard.d.ts +4 -0
- package/dist/esm/components/LogCard.js +141 -0
- package/dist/esm/components/MetaAccordion.d.ts +4 -0
- package/dist/esm/components/MetaAccordion.js +108 -0
- package/dist/esm/components/MiniBarChart.d.ts +7 -0
- package/dist/esm/components/MiniBarChart.js +18 -0
- package/dist/esm/components/MiniLineChart.d.ts +6 -0
- package/dist/esm/components/MiniLineChart.js +20 -0
- package/dist/esm/components/NetworkIcons.d.ts +31 -0
- package/dist/esm/components/NetworkIcons.js +176 -0
- package/dist/esm/components/SectionHeader.d.ts +4 -0
- package/dist/esm/components/SectionHeader.js +49 -0
- package/dist/esm/components/SourcePageCard.d.ts +4 -0
- package/dist/esm/components/SourcePageCard.js +94 -0
- package/dist/esm/components/TouchableScale.d.ts +9 -0
- package/dist/esm/components/TouchableScale.js +9 -0
- package/dist/esm/components/TreeNode.d.ts +4 -0
- package/dist/esm/components/TreeNode.js +102 -0
- package/dist/esm/constants/index.d.ts +7 -0
- package/dist/esm/constants/index.js +32 -0
- package/dist/esm/customHooks/analyticsLogger.d.ts +21 -0
- package/dist/esm/customHooks/analyticsLogger.js +152 -0
- package/dist/esm/customHooks/consoleLogger.d.ts +5 -0
- package/dist/esm/customHooks/consoleLogger.js +134 -0
- package/dist/esm/customHooks/logFilters.d.ts +5 -0
- package/dist/esm/customHooks/logFilters.js +31 -0
- package/dist/esm/customHooks/networkLogger.d.ts +20 -0
- package/dist/esm/customHooks/networkLogger.js +264 -0
- package/dist/esm/customHooks/useAccordion.d.ts +17 -0
- package/dist/esm/customHooks/useAccordion.js +46 -0
- package/dist/esm/customHooks/webViewLogger.d.ts +22 -0
- package/dist/esm/customHooks/webViewLogger.js +365 -0
- package/dist/esm/helpers/index.d.ts +20 -0
- package/dist/esm/helpers/index.js +207 -0
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.js +2611 -0
- package/dist/esm/styles/AppColors.d.ts +27 -0
- package/dist/esm/styles/AppColors.js +27 -0
- package/dist/esm/styles/AppFonts.d.ts +7 -0
- package/dist/esm/styles/AppFonts.js +7 -0
- package/dist/esm/styles/index.d.ts +1488 -0
- package/dist/esm/styles/index.js +1355 -0
- package/dist/esm/types/index.d.ts +127 -0
- package/dist/esm/types/index.js +1 -0
- package/fonts/Inter/Inter.ttc +0 -0
- package/fonts/Inter/InterVariable-Italic.ttf +0 -0
- package/fonts/Inter/InterVariable.ttf +0 -0
- package/fonts/Inter/LICENSE.txt +92 -0
- package/fonts/Inter/extras/otf/Inter-Black.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-BlackItalic.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-Bold.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-BoldItalic.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-ExtraBold.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-ExtraBoldItalic.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-ExtraLight.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-ExtraLightItalic.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-Italic.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-Light.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-LightItalic.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-Medium.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-MediumItalic.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-Regular.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-SemiBold.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-SemiBoldItalic.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-Thin.otf +0 -0
- package/fonts/Inter/extras/otf/Inter-ThinItalic.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-Black.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-BlackItalic.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-Bold.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-BoldItalic.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-ExtraBold.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-ExtraBoldItalic.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-ExtraLight.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-ExtraLightItalic.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-Italic.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-Light.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-LightItalic.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-Medium.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-MediumItalic.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-Regular.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-SemiBold.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-SemiBoldItalic.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-Thin.otf +0 -0
- package/fonts/Inter/extras/otf/InterDisplay-ThinItalic.otf +0 -0
- package/fonts/Inter/extras/ttf/Inter-Black.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-BlackItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-Bold.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-BoldItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-ExtraBold.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-ExtraBoldItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-ExtraLight.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-ExtraLightItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-Italic.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-Light.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-LightItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-Medium.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-MediumItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-Regular.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-SemiBold.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-SemiBoldItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-Thin.ttf +0 -0
- package/fonts/Inter/extras/ttf/Inter-ThinItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-Black.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-BlackItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-Bold.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-BoldItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-ExtraBold.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-ExtraBoldItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-ExtraLight.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-ExtraLightItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-Italic.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-Light.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-LightItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-Medium.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-MediumItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-Regular.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-SemiBold.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-SemiBoldItalic.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-Thin.ttf +0 -0
- package/fonts/Inter/extras/ttf/InterDisplay-ThinItalic.ttf +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-Black.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-BlackItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-Bold.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-BoldItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-ExtraBold.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-ExtraBoldItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-ExtraLight.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-ExtraLightItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-Italic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-Light.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-LightItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-Medium.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-MediumItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-Regular.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-SemiBold.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-SemiBoldItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-Thin.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/Inter-ThinItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-Black.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-BlackItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-Bold.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-BoldItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-ExtraBold.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-ExtraBoldItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-ExtraLight.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-ExtraLightItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-Italic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-Light.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-LightItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-Medium.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-MediumItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-Regular.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-SemiBold.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-SemiBoldItalic.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-Thin.woff2 +0 -0
- package/fonts/Inter/extras/woff-hinted/InterDisplay-ThinItalic.woff2 +0 -0
- package/fonts/Inter/help.txt +165 -0
- package/fonts/Inter/web/Inter-Black.woff2 +0 -0
- package/fonts/Inter/web/Inter-BlackItalic.woff2 +0 -0
- package/fonts/Inter/web/Inter-Bold.woff2 +0 -0
- package/fonts/Inter/web/Inter-BoldItalic.woff2 +0 -0
- package/fonts/Inter/web/Inter-ExtraBold.woff2 +0 -0
- package/fonts/Inter/web/Inter-ExtraBoldItalic.woff2 +0 -0
- package/fonts/Inter/web/Inter-ExtraLight.woff2 +0 -0
- package/fonts/Inter/web/Inter-ExtraLightItalic.woff2 +0 -0
- package/fonts/Inter/web/Inter-Italic.woff2 +0 -0
- package/fonts/Inter/web/Inter-Light.woff2 +0 -0
- package/fonts/Inter/web/Inter-LightItalic.woff2 +0 -0
- package/fonts/Inter/web/Inter-Medium.woff2 +0 -0
- package/fonts/Inter/web/Inter-MediumItalic.woff2 +0 -0
- package/fonts/Inter/web/Inter-Regular.woff2 +0 -0
- package/fonts/Inter/web/Inter-SemiBold.woff2 +0 -0
- package/fonts/Inter/web/Inter-SemiBoldItalic.woff2 +0 -0
- package/fonts/Inter/web/Inter-Thin.woff2 +0 -0
- package/fonts/Inter/web/Inter-ThinItalic.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-Black.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-BlackItalic.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-Bold.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-BoldItalic.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-ExtraBold.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-ExtraBoldItalic.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-ExtraLight.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-ExtraLightItalic.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-Italic.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-Light.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-LightItalic.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-Medium.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-MediumItalic.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-Regular.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-SemiBold.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-SemiBoldItalic.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-Thin.woff2 +0 -0
- package/fonts/Inter/web/InterDisplay-ThinItalic.woff2 +0 -0
- package/fonts/Inter/web/InterVariable-Italic.woff2 +0 -0
- package/fonts/Inter/web/InterVariable.woff2 +0 -0
- package/fonts/Inter/web/inter.css +148 -0
- package/package.json +52 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// ─── Analytics Logger ─────────────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Captures @react-native-firebase/analytics events by monkey-patching the
|
|
4
|
+
// analytics instance returned by `analytics()`.
|
|
5
|
+
//
|
|
6
|
+
// Setup (call once at app startup, before any analytics calls):
|
|
7
|
+
//
|
|
8
|
+
// import analytics from '@react-native-firebase/analytics';
|
|
9
|
+
// import { setupAnalyticsLogger } from './network/analyticsLogger';
|
|
10
|
+
//
|
|
11
|
+
// setupAnalyticsLogger(analytics());
|
|
12
|
+
//
|
|
13
|
+
// That's it — every subsequent logEvent / logScreenView / setUserProperty call
|
|
14
|
+
// will be intercepted and shown in the Analytics tab of NetworkInspector.
|
|
15
|
+
//
|
|
16
|
+
// Patched methods:
|
|
17
|
+
// logEvent(name, params)
|
|
18
|
+
// logScreenView({ screen_name, screen_class })
|
|
19
|
+
// setUserProperty(name, value)
|
|
20
|
+
// setUserProperties(properties)
|
|
21
|
+
// setUserId(id)
|
|
22
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
23
|
+
// ─── Internal state ───────────────────────────────────────────────────────────
|
|
24
|
+
let events = [];
|
|
25
|
+
let listeners = [];
|
|
26
|
+
let counter = 0;
|
|
27
|
+
// Running snapshot of user properties set so far — attached to every event
|
|
28
|
+
let currentUserProperties = {};
|
|
29
|
+
let currentUserId;
|
|
30
|
+
// ─── Core helpers ─────────────────────────────────────────────────────────────
|
|
31
|
+
const notify = () => {
|
|
32
|
+
const snapshot = [...events];
|
|
33
|
+
listeners.forEach((cb) => cb(snapshot));
|
|
34
|
+
};
|
|
35
|
+
const addEvent = (event) => {
|
|
36
|
+
events.unshift(event);
|
|
37
|
+
events = events.slice(0, 200);
|
|
38
|
+
notify();
|
|
39
|
+
};
|
|
40
|
+
// ─── Public subscribe / query API ────────────────────────────────────────────
|
|
41
|
+
export const subscribeAnalyticsEvents = (callback) => {
|
|
42
|
+
listeners.push(callback);
|
|
43
|
+
callback([...events]);
|
|
44
|
+
return () => {
|
|
45
|
+
listeners = listeners.filter((l) => l !== callback);
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export const clearAnalyticsEvents = () => {
|
|
49
|
+
events = [];
|
|
50
|
+
notify();
|
|
51
|
+
};
|
|
52
|
+
export const getAnalyticsEvents = () => [...events];
|
|
53
|
+
// ─── Manual logging (escape hatch, rarely needed) ────────────────────────────
|
|
54
|
+
/**
|
|
55
|
+
* Directly push an event into the inspector without going through Firebase.
|
|
56
|
+
* Useful for custom analytics wrappers or testing.
|
|
57
|
+
*/
|
|
58
|
+
export const logAnalyticsEvent = (name, params = {}, userProperties = {}) => {
|
|
59
|
+
addEvent({
|
|
60
|
+
id: counter++,
|
|
61
|
+
name,
|
|
62
|
+
params,
|
|
63
|
+
userProperties: { ...currentUserProperties, ...userProperties },
|
|
64
|
+
timestamp: Date.now(),
|
|
65
|
+
source: "manual",
|
|
66
|
+
userId: currentUserId ?? "",
|
|
67
|
+
screenName: "",
|
|
68
|
+
screenClass: "",
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
// ─── Firebase Analytics instance patcher ─────────────────────────────────────
|
|
72
|
+
/**
|
|
73
|
+
* Monkey-patches a @react-native-firebase/analytics instance so all calls
|
|
74
|
+
* are intercepted and forwarded to the NetworkInspector analytics tab.
|
|
75
|
+
*
|
|
76
|
+
* Pass the result of `analytics()` (the default app instance or any named one).
|
|
77
|
+
* Safe to call multiple times with the same instance — won't double-patch.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* import analytics from '@react-native-firebase/analytics';
|
|
81
|
+
* setupAnalyticsLogger(analytics());
|
|
82
|
+
*/
|
|
83
|
+
export const setupAnalyticsLogger = (analyticsInstance) => {
|
|
84
|
+
if (!analyticsInstance) {
|
|
85
|
+
console.warn("[AnalyticsLogger] No analytics instance provided — skipping setup.");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Guard against double-patching the same instance
|
|
89
|
+
if (analyticsInstance.__INSPECTOR_PATCHED__)
|
|
90
|
+
return;
|
|
91
|
+
analyticsInstance.__INSPECTOR_PATCHED__ = true;
|
|
92
|
+
// ── logEvent ──────────────────────────────────────────────────────────────
|
|
93
|
+
const originalLogEvent = analyticsInstance.logEvent.bind(analyticsInstance);
|
|
94
|
+
analyticsInstance.logEvent = async (name, params) => {
|
|
95
|
+
addEvent({
|
|
96
|
+
id: counter++,
|
|
97
|
+
name,
|
|
98
|
+
params: params ?? {},
|
|
99
|
+
userProperties: { ...currentUserProperties },
|
|
100
|
+
timestamp: Date.now(),
|
|
101
|
+
source: "firebase",
|
|
102
|
+
userId: currentUserId ?? "",
|
|
103
|
+
screenName: "",
|
|
104
|
+
screenClass: "",
|
|
105
|
+
});
|
|
106
|
+
return originalLogEvent(name, params);
|
|
107
|
+
};
|
|
108
|
+
// ── logScreenView ─────────────────────────────────────────────────────────
|
|
109
|
+
const originalLogScreenView = analyticsInstance.logScreenView.bind(analyticsInstance);
|
|
110
|
+
analyticsInstance.logScreenView = async (params) => {
|
|
111
|
+
addEvent({
|
|
112
|
+
id: counter++,
|
|
113
|
+
name: "screen_view",
|
|
114
|
+
params: params ?? {},
|
|
115
|
+
userProperties: { ...currentUserProperties },
|
|
116
|
+
timestamp: Date.now(),
|
|
117
|
+
source: "firebase",
|
|
118
|
+
screenName: params?.screen_name ?? "",
|
|
119
|
+
screenClass: params?.screen_class ?? "",
|
|
120
|
+
userId: currentUserId ?? "",
|
|
121
|
+
});
|
|
122
|
+
return originalLogScreenView(params);
|
|
123
|
+
};
|
|
124
|
+
// ── setUserProperty ───────────────────────────────────────────────────────
|
|
125
|
+
const originalSetUserProperty = analyticsInstance.setUserProperty.bind(analyticsInstance);
|
|
126
|
+
analyticsInstance.setUserProperty = async (name, value) => {
|
|
127
|
+
if (value === null) {
|
|
128
|
+
delete currentUserProperties[name];
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
currentUserProperties[name] = value;
|
|
132
|
+
}
|
|
133
|
+
return originalSetUserProperty(name, value);
|
|
134
|
+
};
|
|
135
|
+
// ── setUserProperties ─────────────────────────────────────────────────────
|
|
136
|
+
const originalSetUserProperties = analyticsInstance.setUserProperties.bind(analyticsInstance);
|
|
137
|
+
analyticsInstance.setUserProperties = async (properties) => {
|
|
138
|
+
Object.entries(properties).forEach(([k, v]) => {
|
|
139
|
+
if (v === null)
|
|
140
|
+
delete currentUserProperties[k];
|
|
141
|
+
else
|
|
142
|
+
currentUserProperties[k] = v;
|
|
143
|
+
});
|
|
144
|
+
return originalSetUserProperties(properties);
|
|
145
|
+
};
|
|
146
|
+
// ── setUserId ─────────────────────────────────────────────────────────────
|
|
147
|
+
const originalSetUserId = analyticsInstance.setUserId.bind(analyticsInstance);
|
|
148
|
+
analyticsInstance.setUserId = async (id) => {
|
|
149
|
+
currentUserId = id ?? undefined;
|
|
150
|
+
return originalSetUserId(id);
|
|
151
|
+
};
|
|
152
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ConsoleLog } from '../types';
|
|
2
|
+
export declare const subscribeConsoleLogs: (callback: (logs: ConsoleLog[]) => void) => () => void;
|
|
3
|
+
export declare const clearConsoleLogs: () => void;
|
|
4
|
+
export declare const getConsoleLogs: () => ConsoleLog[];
|
|
5
|
+
export declare const setupConsoleLogger: () => void;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { IGNORED_LOG_PREFIXES } from './logFilters';
|
|
2
|
+
let logs = [];
|
|
3
|
+
let listeners = [];
|
|
4
|
+
let counter = 0;
|
|
5
|
+
let isIntercepting = false;
|
|
6
|
+
const MAX_LOGS = 100;
|
|
7
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
8
|
+
const formatArgs = (args) => {
|
|
9
|
+
return args
|
|
10
|
+
.map(arg => {
|
|
11
|
+
if (arg === null)
|
|
12
|
+
return 'null';
|
|
13
|
+
if (arg === undefined)
|
|
14
|
+
return 'undefined';
|
|
15
|
+
if (typeof arg === 'object') {
|
|
16
|
+
try {
|
|
17
|
+
return JSON.stringify(arg, null, 2);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return Object.prototype.toString.call(arg);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return String(arg);
|
|
24
|
+
})
|
|
25
|
+
.join(' ');
|
|
26
|
+
};
|
|
27
|
+
const getCallerFromStack = () => {
|
|
28
|
+
try {
|
|
29
|
+
const stack = new Error().stack;
|
|
30
|
+
if (!stack)
|
|
31
|
+
return 'Unknown';
|
|
32
|
+
const lines = stack.split('\n');
|
|
33
|
+
for (let i = 0; i < lines.length; i++) {
|
|
34
|
+
const line = lines[i];
|
|
35
|
+
// Skip internal console logger stack frames and native helpers
|
|
36
|
+
if (line.includes('consoleLogger') ||
|
|
37
|
+
line.includes('setupConsoleLogger') ||
|
|
38
|
+
line.includes('node_modules') ||
|
|
39
|
+
line.includes('Error')) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
return line.trim().replace(/^at /, '');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (e) { }
|
|
46
|
+
return 'Unknown';
|
|
47
|
+
};
|
|
48
|
+
const notify = () => {
|
|
49
|
+
const snapshot = [...logs];
|
|
50
|
+
listeners.forEach(cb => cb(snapshot));
|
|
51
|
+
};
|
|
52
|
+
const addLog = (type, args, sourceMethod) => {
|
|
53
|
+
if (isIntercepting)
|
|
54
|
+
return;
|
|
55
|
+
isIntercepting = true;
|
|
56
|
+
try {
|
|
57
|
+
const message = formatArgs(args);
|
|
58
|
+
// Check if the log should be ignored based on starting prefixes across all categories
|
|
59
|
+
const allPrefixes = [
|
|
60
|
+
...((IGNORED_LOG_PREFIXES && IGNORED_LOG_PREFIXES.info) || []),
|
|
61
|
+
...((IGNORED_LOG_PREFIXES && IGNORED_LOG_PREFIXES.warn) || []),
|
|
62
|
+
...((IGNORED_LOG_PREFIXES && IGNORED_LOG_PREFIXES.error) || []),
|
|
63
|
+
].filter(p => typeof p === 'string' && p.trim().length > 0);
|
|
64
|
+
if (allPrefixes.some(prefix => message
|
|
65
|
+
.toLowerCase()
|
|
66
|
+
.trim()
|
|
67
|
+
.startsWith(prefix.toLowerCase().trim()) ||
|
|
68
|
+
message.toLowerCase().trim().includes(prefix.toLowerCase().trim()))) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const caller = getCallerFromStack();
|
|
72
|
+
const newLog = {
|
|
73
|
+
id: counter++,
|
|
74
|
+
type,
|
|
75
|
+
message,
|
|
76
|
+
timestamp: Date.now(),
|
|
77
|
+
caller,
|
|
78
|
+
sourceMethod,
|
|
79
|
+
};
|
|
80
|
+
logs.unshift(newLog);
|
|
81
|
+
logs = logs.slice(0, MAX_LOGS);
|
|
82
|
+
notify();
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
// Fail-safe to prevent crash during logging
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
isIntercepting = false;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
92
|
+
export const subscribeConsoleLogs = (callback) => {
|
|
93
|
+
listeners.push(callback);
|
|
94
|
+
callback([...logs]);
|
|
95
|
+
return () => {
|
|
96
|
+
listeners = listeners.filter(l => l !== callback);
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
export const clearConsoleLogs = () => {
|
|
100
|
+
logs = [];
|
|
101
|
+
notify();
|
|
102
|
+
};
|
|
103
|
+
export const getConsoleLogs = () => [...logs];
|
|
104
|
+
export const setupConsoleLogger = () => {
|
|
105
|
+
if (global.__CONSOLE_LOGGER_INITIALIZED__)
|
|
106
|
+
return;
|
|
107
|
+
const originalConsole = {
|
|
108
|
+
log: console.log,
|
|
109
|
+
info: console.info,
|
|
110
|
+
warn: console.warn,
|
|
111
|
+
error: console.error,
|
|
112
|
+
};
|
|
113
|
+
// Intercept console.log
|
|
114
|
+
console.log = (...args) => {
|
|
115
|
+
addLog('info', args, 'log');
|
|
116
|
+
originalConsole.log(...args);
|
|
117
|
+
};
|
|
118
|
+
// Intercept console.info
|
|
119
|
+
console.info = (...args) => {
|
|
120
|
+
addLog('info', args, 'info');
|
|
121
|
+
originalConsole.info(...args);
|
|
122
|
+
};
|
|
123
|
+
// Intercept console.warn
|
|
124
|
+
console.warn = (...args) => {
|
|
125
|
+
addLog('warn', args, 'warn');
|
|
126
|
+
originalConsole.warn(...args);
|
|
127
|
+
};
|
|
128
|
+
// Intercept console.error
|
|
129
|
+
console.error = (...args) => {
|
|
130
|
+
addLog('error', args, 'error');
|
|
131
|
+
originalConsole.error(...args);
|
|
132
|
+
};
|
|
133
|
+
global.__CONSOLE_LOGGER_INITIALIZED__ = true;
|
|
134
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for console logs to ignore.
|
|
3
|
+
* Logs matching any of these starting prefixes will be filtered out.
|
|
4
|
+
*/
|
|
5
|
+
export const IGNORED_LOG_PREFIXES = {
|
|
6
|
+
info: [
|
|
7
|
+
// Add prefixes of info logs you want to ignore, e.g.:
|
|
8
|
+
// 'Starting server',
|
|
9
|
+
'VirtualizedList: You have a large list that is slow to update',
|
|
10
|
+
],
|
|
11
|
+
warn: [
|
|
12
|
+
// Add prefixes of warning logs you want to ignore, e.g.:
|
|
13
|
+
// 'Require cycle:',
|
|
14
|
+
// 'ViewPropTypes will be removed',
|
|
15
|
+
'This method is deprecated (as well as all React Native Firebase namespaced API) and will be removed in the next major release as part of move to match Firebase Web modular SDK API.',
|
|
16
|
+
'SerializableStateInvariantMiddleware took',
|
|
17
|
+
'Non-serializable values were found in the navigation state.',
|
|
18
|
+
'SafeAreaView has been deprecated and will be removed in a future release.',
|
|
19
|
+
'Clipboard has been extracted from react-native core and will be removed in a future release.',
|
|
20
|
+
'You should always pass contentWidth prop to properly handle screen rotations and have a seamless support for images scaling.',
|
|
21
|
+
'Selector unknown returned a different result when called with the same parameters.',
|
|
22
|
+
'You seem to update props of the "TRenderEngineProvider" component in short periods of time',
|
|
23
|
+
'A non-serializable value was detected in an action',
|
|
24
|
+
],
|
|
25
|
+
error: [
|
|
26
|
+
// Add prefixes of error logs you want to ignore, e.g.:
|
|
27
|
+
// 'Warning: Each child in a list should have a unique',
|
|
28
|
+
'A non-serializable value was detected in the state, in the path: `tierStatusCalculator.date`',
|
|
29
|
+
'VirtualizedLists should never be nested inside plain ScrollViews with the same orientation because it can break windowing and other functionality - use another VirtualizedList-backed container instead.',
|
|
30
|
+
],
|
|
31
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import './webViewLogger';
|
|
2
|
+
type NetworkLog = {
|
|
3
|
+
id: number;
|
|
4
|
+
url: string;
|
|
5
|
+
method: string;
|
|
6
|
+
status?: number;
|
|
7
|
+
request?: any;
|
|
8
|
+
response?: any;
|
|
9
|
+
duration?: number;
|
|
10
|
+
startTime: number;
|
|
11
|
+
caller?: string;
|
|
12
|
+
requestHeaders?: Record<string, string>;
|
|
13
|
+
responseHeaders?: Record<string, string>;
|
|
14
|
+
};
|
|
15
|
+
export declare const subscribeNetworkLogs: (callback: (logs: NetworkLog[]) => void) => () => void;
|
|
16
|
+
export declare const clearNetworkLogs: () => void;
|
|
17
|
+
export declare const getNetworkLogs: () => NetworkLog[];
|
|
18
|
+
export declare const setupNetworkLogger: () => void;
|
|
19
|
+
export declare const addAxiosInterceptors: (axiosInstance: any) => void;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import './webViewLogger';
|
|
2
|
+
let logs = [];
|
|
3
|
+
let listeners = [];
|
|
4
|
+
let counter = 0;
|
|
5
|
+
const ALLOWED_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
|
|
6
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
7
|
+
function normaliseHeaders(raw) {
|
|
8
|
+
if (!raw)
|
|
9
|
+
return undefined;
|
|
10
|
+
if (typeof raw.forEach === 'function') {
|
|
11
|
+
const result = {};
|
|
12
|
+
raw.forEach((value, key) => {
|
|
13
|
+
result[key] = value;
|
|
14
|
+
});
|
|
15
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
16
|
+
}
|
|
17
|
+
if (Array.isArray(raw)) {
|
|
18
|
+
const result = {};
|
|
19
|
+
raw.forEach(([key, value]) => {
|
|
20
|
+
result[key] = value;
|
|
21
|
+
});
|
|
22
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
23
|
+
}
|
|
24
|
+
const obj = raw;
|
|
25
|
+
const result = {};
|
|
26
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
27
|
+
if (value != null) {
|
|
28
|
+
result[key] = String(value);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
32
|
+
}
|
|
33
|
+
// ✅ Parse FormData for File Upload previews
|
|
34
|
+
function parseRequestData(data) {
|
|
35
|
+
if (!data)
|
|
36
|
+
return data;
|
|
37
|
+
if (data && data._parts && Array.isArray(data._parts)) {
|
|
38
|
+
const parsedFormData = {};
|
|
39
|
+
data._parts.forEach((part) => {
|
|
40
|
+
const key = part[0];
|
|
41
|
+
const value = part[1];
|
|
42
|
+
if (value && typeof value === 'object' && value.uri) {
|
|
43
|
+
parsedFormData[key] = {
|
|
44
|
+
_isFile: true,
|
|
45
|
+
name: value.name || 'unknown',
|
|
46
|
+
type: value.type || 'unknown',
|
|
47
|
+
uri: value.uri,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
parsedFormData[key] = value;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return { _isFormData: true, ...parsedFormData };
|
|
55
|
+
}
|
|
56
|
+
return data;
|
|
57
|
+
}
|
|
58
|
+
// ✅ Magic function to extract file and line number from the call stack
|
|
59
|
+
function getCallerFromStack() {
|
|
60
|
+
try {
|
|
61
|
+
const stack = new Error().stack;
|
|
62
|
+
if (!stack)
|
|
63
|
+
return 'Unknown';
|
|
64
|
+
const lines = stack.split('\n');
|
|
65
|
+
for (let i = 0; i < lines.length; i++) {
|
|
66
|
+
const line = lines[i];
|
|
67
|
+
// Skip internal react-native network modules and the logger itself
|
|
68
|
+
if (line.includes('networkLogger') ||
|
|
69
|
+
line.includes('node_modules') ||
|
|
70
|
+
line.includes('Error') ||
|
|
71
|
+
line.includes('regeneratorRuntime')) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
return line.trim().replace(/^at /, '');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (e) { }
|
|
78
|
+
return 'Unknown';
|
|
79
|
+
}
|
|
80
|
+
// ─── Subscribe ────────────────────────────────────────────────────────────────
|
|
81
|
+
export const subscribeNetworkLogs = (callback) => {
|
|
82
|
+
listeners.push(callback);
|
|
83
|
+
callback([...logs]);
|
|
84
|
+
return () => {
|
|
85
|
+
listeners = listeners.filter(l => l !== callback);
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
export const clearNetworkLogs = () => {
|
|
89
|
+
logs = [];
|
|
90
|
+
notify();
|
|
91
|
+
};
|
|
92
|
+
export const getNetworkLogs = () => [...logs];
|
|
93
|
+
// ─── Internal ─────────────────────────────────────────────────────────────────
|
|
94
|
+
const notify = () => {
|
|
95
|
+
const snapshot = [...logs];
|
|
96
|
+
listeners.forEach(cb => cb(snapshot));
|
|
97
|
+
};
|
|
98
|
+
const addOrUpdateLog = (log) => {
|
|
99
|
+
const method = log.method?.toUpperCase();
|
|
100
|
+
if (!ALLOWED_METHODS.includes(method))
|
|
101
|
+
return;
|
|
102
|
+
const index = logs.findIndex(l => l.id === log.id);
|
|
103
|
+
if (index >= 0) {
|
|
104
|
+
logs[index] = { ...logs[index], ...log };
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
logs.unshift(log);
|
|
108
|
+
}
|
|
109
|
+
logs = logs.slice(0, 100);
|
|
110
|
+
notify();
|
|
111
|
+
};
|
|
112
|
+
// ─── Setup ────────────────────────────────────────────────────────────────────
|
|
113
|
+
export const setupNetworkLogger = () => {
|
|
114
|
+
if (global.__NETWORK_LOGGER_INITIALIZED__)
|
|
115
|
+
return;
|
|
116
|
+
global.__NETWORK_LOGGER__ = addOrUpdateLog;
|
|
117
|
+
const originalFetch = global.fetch;
|
|
118
|
+
if (originalFetch) {
|
|
119
|
+
global.fetch = async (url, options = {}) => {
|
|
120
|
+
const method = (options?.method || 'GET').toUpperCase();
|
|
121
|
+
if (!ALLOWED_METHODS.includes(method))
|
|
122
|
+
return originalFetch(url, options);
|
|
123
|
+
const id = counter++;
|
|
124
|
+
const start = Date.now();
|
|
125
|
+
const finalUrl = typeof url === 'string' ? url : url?.url;
|
|
126
|
+
const requestHeaders = normaliseHeaders(options?.headers);
|
|
127
|
+
const caller = getCallerFromStack(); // ✅ Capture call line
|
|
128
|
+
addOrUpdateLog({
|
|
129
|
+
id,
|
|
130
|
+
url: finalUrl,
|
|
131
|
+
method,
|
|
132
|
+
startTime: start,
|
|
133
|
+
caller,
|
|
134
|
+
request: method === 'GET' ? undefined : parseRequestData(options?.body),
|
|
135
|
+
requestHeaders,
|
|
136
|
+
});
|
|
137
|
+
try {
|
|
138
|
+
const response = await originalFetch(url, options);
|
|
139
|
+
const duration = Date.now() - start;
|
|
140
|
+
const responseHeaders = normaliseHeaders(response.headers);
|
|
141
|
+
let data = null;
|
|
142
|
+
const contentType = responseHeaders?.['content-type'] ||
|
|
143
|
+
responseHeaders?.['Content-Type'] ||
|
|
144
|
+
'';
|
|
145
|
+
if (contentType.includes('image/')) {
|
|
146
|
+
data = '[Image Data]';
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
try {
|
|
150
|
+
const clone = response.clone();
|
|
151
|
+
const text = await clone.text();
|
|
152
|
+
try {
|
|
153
|
+
data = JSON.parse(text);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
data = text;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch { }
|
|
160
|
+
}
|
|
161
|
+
addOrUpdateLog({
|
|
162
|
+
id,
|
|
163
|
+
url: finalUrl,
|
|
164
|
+
method,
|
|
165
|
+
status: response.status,
|
|
166
|
+
response: data,
|
|
167
|
+
duration,
|
|
168
|
+
startTime: start,
|
|
169
|
+
caller,
|
|
170
|
+
responseHeaders,
|
|
171
|
+
});
|
|
172
|
+
return response;
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
addOrUpdateLog({
|
|
176
|
+
id,
|
|
177
|
+
url: finalUrl,
|
|
178
|
+
method,
|
|
179
|
+
status: 0,
|
|
180
|
+
startTime: start,
|
|
181
|
+
response: error,
|
|
182
|
+
caller,
|
|
183
|
+
duration: Date.now() - start,
|
|
184
|
+
});
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
global.__NETWORK_LOGGER_INITIALIZED__ = true;
|
|
190
|
+
};
|
|
191
|
+
// ─── Axios interceptor helper ─────────────────────────────────────────────────
|
|
192
|
+
export const addAxiosInterceptors = (axiosInstance) => {
|
|
193
|
+
axiosInstance.interceptors.request.use(async (config) => {
|
|
194
|
+
const method = (config.method || 'GET').toUpperCase();
|
|
195
|
+
if (!ALLOWED_METHODS.includes(method))
|
|
196
|
+
return config;
|
|
197
|
+
const id = counter++;
|
|
198
|
+
const start = Date.now();
|
|
199
|
+
const caller = getCallerFromStack(); // ✅ Capture call line
|
|
200
|
+
config.__logId = id;
|
|
201
|
+
config.__logStart = start;
|
|
202
|
+
config.__logCaller = caller;
|
|
203
|
+
let url = config.url ?? '';
|
|
204
|
+
if (!url.startsWith('http'))
|
|
205
|
+
url = `${config.baseURL ?? ''}${url}`;
|
|
206
|
+
addOrUpdateLog({
|
|
207
|
+
id,
|
|
208
|
+
url,
|
|
209
|
+
method,
|
|
210
|
+
startTime: start,
|
|
211
|
+
caller,
|
|
212
|
+
request: method === 'GET' ? undefined : parseRequestData(config.data),
|
|
213
|
+
requestHeaders: normaliseHeaders(config.headers),
|
|
214
|
+
});
|
|
215
|
+
return config;
|
|
216
|
+
});
|
|
217
|
+
axiosInstance.interceptors.response.use((response) => {
|
|
218
|
+
const config = response.config || {};
|
|
219
|
+
const id = config.__logId;
|
|
220
|
+
const start = config.__logStart;
|
|
221
|
+
const caller = config.__logCaller;
|
|
222
|
+
const method = (config.method || 'GET').toUpperCase();
|
|
223
|
+
if (id == null || !ALLOWED_METHODS.includes(method))
|
|
224
|
+
return response;
|
|
225
|
+
let url = config.url ?? '';
|
|
226
|
+
if (!url.startsWith('http'))
|
|
227
|
+
url = `${config.baseURL ?? ''}${url}`;
|
|
228
|
+
addOrUpdateLog({
|
|
229
|
+
id,
|
|
230
|
+
url,
|
|
231
|
+
method,
|
|
232
|
+
status: response.status,
|
|
233
|
+
response: response.data,
|
|
234
|
+
startTime: start || Date.now(),
|
|
235
|
+
duration: start != null ? Date.now() - start : undefined,
|
|
236
|
+
caller,
|
|
237
|
+
responseHeaders: normaliseHeaders(response.headers),
|
|
238
|
+
});
|
|
239
|
+
return response;
|
|
240
|
+
}, (error) => {
|
|
241
|
+
const config = error.config || {};
|
|
242
|
+
const id = config.__logId;
|
|
243
|
+
const start = config.__logStart;
|
|
244
|
+
const caller = config.__logCaller;
|
|
245
|
+
const method = (config.method || 'GET').toUpperCase();
|
|
246
|
+
if (id != null && ALLOWED_METHODS.includes(method)) {
|
|
247
|
+
let url = config.url ?? '';
|
|
248
|
+
if (!url.startsWith('http'))
|
|
249
|
+
url = `${config.baseURL ?? ''}${url}`;
|
|
250
|
+
addOrUpdateLog({
|
|
251
|
+
id,
|
|
252
|
+
url,
|
|
253
|
+
method,
|
|
254
|
+
status: error.response?.status ?? 0,
|
|
255
|
+
response: error.response?.data ?? error.message,
|
|
256
|
+
startTime: start || Date.now(),
|
|
257
|
+
duration: start != null ? Date.now() - start : undefined,
|
|
258
|
+
caller,
|
|
259
|
+
responseHeaders: normaliseHeaders(error.response?.headers),
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
return Promise.reject(error);
|
|
263
|
+
});
|
|
264
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Animated } from 'react-native';
|
|
2
|
+
declare const useAccordion: (initialOpen?: boolean, maxBodyHeight?: number, duration?: number) => {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
toggleOpen: () => void;
|
|
5
|
+
forceOpen: (open: boolean) => void;
|
|
6
|
+
chevronStyle: {
|
|
7
|
+
transform: {
|
|
8
|
+
rotate: Animated.AnimatedInterpolation<string | number>;
|
|
9
|
+
}[];
|
|
10
|
+
};
|
|
11
|
+
bodyStyle: {
|
|
12
|
+
maxHeight: Animated.AnimatedInterpolation<string | number>;
|
|
13
|
+
overflow: "hidden";
|
|
14
|
+
opacity: Animated.AnimatedInterpolation<string | number>;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export default useAccordion;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from 'react';
|
|
2
|
+
import { Animated } from 'react-native';
|
|
3
|
+
const useAccordion = (initialOpen = false, maxBodyHeight = 1200, duration = 280) => {
|
|
4
|
+
const [isOpen, setIsOpen] = useState(initialOpen);
|
|
5
|
+
const animVal = useRef(new Animated.Value(initialOpen ? 1 : 0)).current;
|
|
6
|
+
const toggleOpen = useCallback(() => {
|
|
7
|
+
const next = !isOpen;
|
|
8
|
+
setIsOpen(next);
|
|
9
|
+
Animated.timing(animVal, {
|
|
10
|
+
toValue: next ? 1 : 0,
|
|
11
|
+
duration,
|
|
12
|
+
useNativeDriver: false,
|
|
13
|
+
}).start();
|
|
14
|
+
}, [isOpen, animVal, duration]);
|
|
15
|
+
const forceOpen = useCallback((open) => {
|
|
16
|
+
setIsOpen(open);
|
|
17
|
+
Animated.timing(animVal, {
|
|
18
|
+
toValue: open ? 1 : 0,
|
|
19
|
+
duration,
|
|
20
|
+
useNativeDriver: false,
|
|
21
|
+
}).start();
|
|
22
|
+
}, [animVal, duration]);
|
|
23
|
+
const chevronStyle = {
|
|
24
|
+
transform: [
|
|
25
|
+
{
|
|
26
|
+
rotate: animVal.interpolate({
|
|
27
|
+
inputRange: [0, 1],
|
|
28
|
+
outputRange: ['0deg', '180deg'],
|
|
29
|
+
}),
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
const bodyStyle = {
|
|
34
|
+
maxHeight: animVal.interpolate({
|
|
35
|
+
inputRange: [0, 1],
|
|
36
|
+
outputRange: [0, maxBodyHeight],
|
|
37
|
+
}),
|
|
38
|
+
overflow: 'hidden',
|
|
39
|
+
opacity: animVal.interpolate({
|
|
40
|
+
inputRange: [0, 0.4, 1],
|
|
41
|
+
outputRange: [0, 0.7, 1],
|
|
42
|
+
}),
|
|
43
|
+
};
|
|
44
|
+
return { isOpen, toggleOpen, forceOpen, chevronStyle, bodyStyle };
|
|
45
|
+
};
|
|
46
|
+
export default useAccordion;
|