react-native-inapp-inspector 1.0.14 → 1.0.16

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.
@@ -30,7 +30,7 @@ let currentUserId;
30
30
  // ─── Core helpers ─────────────────────────────────────────────────────────────
31
31
  const notify = () => {
32
32
  const snapshot = [...events];
33
- listeners.forEach((cb) => cb(snapshot));
33
+ listeners.forEach(cb => cb(snapshot));
34
34
  };
35
35
  const addEvent = (event) => {
36
36
  events.unshift(event);
@@ -42,7 +42,7 @@ export const subscribeAnalyticsEvents = (callback) => {
42
42
  listeners.push(callback);
43
43
  callback([...events]);
44
44
  return () => {
45
- listeners = listeners.filter((l) => l !== callback);
45
+ listeners = listeners.filter(l => l !== callback);
46
46
  };
47
47
  };
48
48
  export const clearAnalyticsEvents = () => {
@@ -62,10 +62,10 @@ export const logAnalyticsEvent = (name, params = {}, userProperties = {}) => {
62
62
  params,
63
63
  userProperties: { ...currentUserProperties, ...userProperties },
64
64
  timestamp: Date.now(),
65
- source: "manual",
66
- userId: currentUserId ?? "",
67
- screenName: "",
68
- screenClass: "",
65
+ source: 'manual',
66
+ userId: currentUserId ?? '',
67
+ screenName: '',
68
+ screenClass: '',
69
69
  });
70
70
  };
71
71
  // ─── Firebase Analytics instance patcher ─────────────────────────────────────
@@ -82,7 +82,7 @@ export const logAnalyticsEvent = (name, params = {}, userProperties = {}) => {
82
82
  */
83
83
  export const setupAnalyticsLogger = (analyticsInstance) => {
84
84
  if (!analyticsInstance) {
85
- console.warn("[AnalyticsLogger] No analytics instance provided — skipping setup.");
85
+ console.warn('[AnalyticsLogger] No analytics instance provided — skipping setup.');
86
86
  return;
87
87
  }
88
88
  // Guard against double-patching the same instance
@@ -98,10 +98,10 @@ export const setupAnalyticsLogger = (analyticsInstance) => {
98
98
  params: params ?? {},
99
99
  userProperties: { ...currentUserProperties },
100
100
  timestamp: Date.now(),
101
- source: "firebase",
102
- userId: currentUserId ?? "",
103
- screenName: "",
104
- screenClass: "",
101
+ source: 'firebase',
102
+ userId: currentUserId ?? '',
103
+ screenName: '',
104
+ screenClass: '',
105
105
  });
106
106
  return originalLogEvent(name, params);
107
107
  };
@@ -110,14 +110,14 @@ export const setupAnalyticsLogger = (analyticsInstance) => {
110
110
  analyticsInstance.logScreenView = async (params) => {
111
111
  addEvent({
112
112
  id: counter++,
113
- name: "screen_view",
113
+ name: 'screen_view',
114
114
  params: params ?? {},
115
115
  userProperties: { ...currentUserProperties },
116
116
  timestamp: Date.now(),
117
- source: "firebase",
118
- screenName: params?.screen_name ?? "",
119
- screenClass: params?.screen_class ?? "",
120
- userId: currentUserId ?? "",
117
+ source: 'firebase',
118
+ screenName: params?.screen_name ?? '',
119
+ screenClass: params?.screen_class ?? '',
120
+ userId: currentUserId ?? '',
121
121
  });
122
122
  return originalLogScreenView(params);
123
123
  };
@@ -150,3 +150,42 @@ export const setupAnalyticsLogger = (analyticsInstance) => {
150
150
  return originalSetUserId(id);
151
151
  };
152
152
  };
153
+ export const autoSetupAnalyticsLogger = () => {
154
+ if (globalThis.__INSPECTOR_ANALYTICS_AUTOSETUP__)
155
+ return true;
156
+ let mod;
157
+ try {
158
+ mod = require('@react-native-firebase/analytics'); // optional dep
159
+ }
160
+ catch {
161
+ return false; // GA not installed — silent no-op
162
+ }
163
+ const accessor = mod?.default ?? mod;
164
+ if (typeof accessor !== 'function')
165
+ return false;
166
+ try {
167
+ setupAnalyticsLogger(accessor());
168
+ }
169
+ catch { } // patch default-app instance
170
+ if (!accessor.__INSPECTOR_WRAPPED__) {
171
+ // patch future/named instances
172
+ const wrapped = function (...args) {
173
+ const instance = accessor.apply(this, args);
174
+ try {
175
+ setupAnalyticsLogger(instance);
176
+ }
177
+ catch { }
178
+ return instance;
179
+ };
180
+ Object.setPrototypeOf(wrapped, accessor);
181
+ Object.assign(wrapped, accessor);
182
+ wrapped.__INSPECTOR_WRAPPED__ = true;
183
+ try {
184
+ if (mod.default !== undefined)
185
+ mod.default = wrapped;
186
+ }
187
+ catch { }
188
+ }
189
+ globalThis.__INSPECTOR_ANALYTICS_AUTOSETUP__ = true;
190
+ return true;
191
+ };
@@ -1,4 +1,4 @@
1
- import './webViewLogger';
1
+ import "./webViewLogger";
2
2
  type NetworkLog = {
3
3
  id: number;
4
4
  url: string;
@@ -1,14 +1,20 @@
1
- import './webViewLogger';
2
- import axios from 'axios';
1
+ import "./webViewLogger";
2
+ import axios from "axios";
3
3
  let logs = [];
4
4
  let listeners = [];
5
5
  let counter = 0;
6
- const ALLOWED_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
6
+ const ALLOWED_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
7
+ const IGNORED_URL_PATTERNS = [/\/symbolicate(?:[/?#]|$)/];
8
+ function shouldIgnoreUrl(url) {
9
+ if (!url)
10
+ return false;
11
+ return IGNORED_URL_PATTERNS.some((re) => re.test(url));
12
+ }
7
13
  // ─── Helpers ──────────────────────────────────────────────────────────────────
8
14
  function normaliseHeaders(raw) {
9
15
  if (!raw)
10
16
  return undefined;
11
- if (typeof raw.forEach === 'function') {
17
+ if (typeof raw.forEach === "function") {
12
18
  const result = {};
13
19
  raw.forEach((value, key) => {
14
20
  result[key] = value;
@@ -40,11 +46,11 @@ function parseRequestData(data) {
40
46
  data._parts.forEach((part) => {
41
47
  const key = part[0];
42
48
  const value = part[1];
43
- if (value && typeof value === 'object' && value.uri) {
49
+ if (value && typeof value === "object" && value.uri) {
44
50
  parsedFormData[key] = {
45
51
  _isFile: true,
46
- name: value.name || 'unknown',
47
- type: value.type || 'unknown',
52
+ name: value.name || "unknown",
53
+ type: value.type || "unknown",
48
54
  uri: value.uri,
49
55
  };
50
56
  }
@@ -61,29 +67,29 @@ function getCallerFromStack() {
61
67
  try {
62
68
  const stack = new Error().stack;
63
69
  if (!stack)
64
- return 'Unknown';
65
- const lines = stack.split('\n');
70
+ return "Unknown";
71
+ const lines = stack.split("\n");
66
72
  for (let i = 0; i < lines.length; i++) {
67
73
  const line = lines[i];
68
74
  // Skip internal react-native network modules and the logger itself
69
- if (line.includes('networkLogger') ||
70
- line.includes('node_modules') ||
71
- line.includes('Error') ||
72
- line.includes('regeneratorRuntime')) {
75
+ if (line.includes("networkLogger") ||
76
+ line.includes("node_modules") ||
77
+ line.includes("Error") ||
78
+ line.includes("regeneratorRuntime")) {
73
79
  continue;
74
80
  }
75
- return line.trim().replace(/^at /, '');
81
+ return line.trim().replace(/^at /, "");
76
82
  }
77
83
  }
78
84
  catch (e) { }
79
- return 'Unknown';
85
+ return "Unknown";
80
86
  }
81
87
  // ─── Subscribe ────────────────────────────────────────────────────────────────
82
88
  export const subscribeNetworkLogs = (callback) => {
83
89
  listeners.push(callback);
84
90
  callback([...logs]);
85
91
  return () => {
86
- listeners = listeners.filter(l => l !== callback);
92
+ listeners = listeners.filter((l) => l !== callback);
87
93
  };
88
94
  };
89
95
  export const clearNetworkLogs = () => {
@@ -94,13 +100,15 @@ export const getNetworkLogs = () => [...logs];
94
100
  // ─── Internal ─────────────────────────────────────────────────────────────────
95
101
  const notify = () => {
96
102
  const snapshot = [...logs];
97
- listeners.forEach(cb => cb(snapshot));
103
+ listeners.forEach((cb) => cb(snapshot));
98
104
  };
99
105
  const addOrUpdateLog = (log) => {
100
106
  const method = log.method?.toUpperCase();
101
107
  if (!ALLOWED_METHODS.includes(method))
102
108
  return;
103
- const index = logs.findIndex(l => l.id === log.id);
109
+ if (shouldIgnoreUrl(log.url))
110
+ return;
111
+ const index = logs.findIndex((l) => l.id === log.id);
104
112
  if (index >= 0) {
105
113
  logs[index] = { ...logs[index], ...log };
106
114
  }
@@ -118,12 +126,14 @@ export const setupNetworkLogger = () => {
118
126
  const originalFetch = globalThis.fetch;
119
127
  if (originalFetch) {
120
128
  globalThis.fetch = async (url, options = {}) => {
121
- const method = (options?.method || 'GET').toUpperCase();
129
+ const method = (options?.method || "GET").toUpperCase();
122
130
  if (!ALLOWED_METHODS.includes(method))
123
131
  return originalFetch(url, options);
124
132
  const id = counter++;
125
133
  const start = Date.now();
126
- const finalUrl = typeof url === 'string' ? url : url?.url;
134
+ const finalUrl = typeof url === "string" ? url : url?.url;
135
+ if (shouldIgnoreUrl(finalUrl))
136
+ return originalFetch(url, options);
127
137
  const requestHeaders = normaliseHeaders(options?.headers);
128
138
  const caller = getCallerFromStack(); // ✅ Capture call line
129
139
  addOrUpdateLog({
@@ -132,7 +142,7 @@ export const setupNetworkLogger = () => {
132
142
  method,
133
143
  startTime: start,
134
144
  caller,
135
- request: method === 'GET' ? undefined : parseRequestData(options?.body),
145
+ request: method === "GET" ? undefined : parseRequestData(options?.body),
136
146
  requestHeaders,
137
147
  });
138
148
  try {
@@ -140,11 +150,11 @@ export const setupNetworkLogger = () => {
140
150
  const duration = Date.now() - start;
141
151
  const responseHeaders = normaliseHeaders(response.headers);
142
152
  let data = null;
143
- const contentType = responseHeaders?.['content-type'] ||
144
- responseHeaders?.['Content-Type'] ||
145
- '';
146
- if (contentType.includes('image/')) {
147
- data = '[Image Data]';
153
+ const contentType = responseHeaders?.["content-type"] ||
154
+ responseHeaders?.["Content-Type"] ||
155
+ "";
156
+ if (contentType.includes("image/")) {
157
+ data = "[Image Data]";
148
158
  }
149
159
  else {
150
160
  try {
@@ -187,52 +197,50 @@ export const setupNetworkLogger = () => {
187
197
  }
188
198
  };
189
199
  }
190
- // Hook Axios using the imported module
200
+ // Hook Axios patches both the default instance and any future axios.create() instances
191
201
  try {
192
202
  if (axios) {
193
203
  addAxiosInterceptors(axios);
194
- console.log('✅ Axios interceptors added to imported axios');
195
204
  const originalCreate = axios.create;
196
- if (typeof originalCreate === 'function') {
205
+ if (typeof originalCreate === "function") {
197
206
  axios.create = function (...args) {
198
207
  const instance = originalCreate.apply(this, args);
199
208
  addAxiosInterceptors(instance);
200
- console.log('✅ Axios interceptors added to custom axios instance (imported)');
201
209
  return instance;
202
210
  };
203
211
  }
204
212
  }
205
- else {
206
- console.warn('⚠️ Axios module not found for interceptor setup');
207
- }
208
213
  }
209
- catch (e) {
210
- console.error('❌ Error during Axios interceptor setup', e);
214
+ catch (_e) {
215
+ // Axios not available fetch-only mode
211
216
  }
212
217
  globalThis.__NETWORK_LOGGER_INITIALIZED__ = true;
213
218
  };
214
219
  // ─── Axios interceptor helper ─────────────────────────────────────────────────
215
220
  export const addAxiosInterceptors = (axiosInstance) => {
216
221
  axiosInstance.interceptors.request.use(async (config) => {
217
- const method = (config.method || 'GET').toUpperCase();
222
+ const method = (config.method || "GET").toUpperCase();
218
223
  if (!ALLOWED_METHODS.includes(method))
219
224
  return config;
220
225
  const id = counter++;
221
226
  const start = Date.now();
222
227
  const caller = getCallerFromStack(); // ✅ Capture call line
228
+ let url = config.url ?? "";
229
+ if (!url.startsWith("http"))
230
+ url = `${config.baseURL ?? ""}${url}`;
231
+ // ✅ Leave config untagged so the response interceptor skips it too.
232
+ if (shouldIgnoreUrl(url))
233
+ return config;
223
234
  config.__logId = id;
224
235
  config.__logStart = start;
225
236
  config.__logCaller = caller;
226
- let url = config.url ?? '';
227
- if (!url.startsWith('http'))
228
- url = `${config.baseURL ?? ''}${url}`;
229
237
  addOrUpdateLog({
230
238
  id,
231
239
  url,
232
240
  method,
233
241
  startTime: start,
234
242
  caller,
235
- request: method === 'GET' ? undefined : parseRequestData(config.data),
243
+ request: method === "GET" ? undefined : parseRequestData(config.data),
236
244
  requestHeaders: normaliseHeaders(config.headers),
237
245
  });
238
246
  return config;
@@ -242,12 +250,12 @@ export const addAxiosInterceptors = (axiosInstance) => {
242
250
  const id = config.__logId;
243
251
  const start = config.__logStart;
244
252
  const caller = config.__logCaller;
245
- const method = (config.method || 'GET').toUpperCase();
253
+ const method = (config.method || "GET").toUpperCase();
246
254
  if (id == null || !ALLOWED_METHODS.includes(method))
247
255
  return response;
248
- let url = config.url ?? '';
249
- if (!url.startsWith('http'))
250
- url = `${config.baseURL ?? ''}${url}`;
256
+ let url = config.url ?? "";
257
+ if (!url.startsWith("http"))
258
+ url = `${config.baseURL ?? ""}${url}`;
251
259
  addOrUpdateLog({
252
260
  id,
253
261
  url,
@@ -265,11 +273,11 @@ export const addAxiosInterceptors = (axiosInstance) => {
265
273
  const id = config.__logId;
266
274
  const start = config.__logStart;
267
275
  const caller = config.__logCaller;
268
- const method = (config.method || 'GET').toUpperCase();
276
+ const method = (config.method || "GET").toUpperCase();
269
277
  if (id != null && ALLOWED_METHODS.includes(method)) {
270
- let url = config.url ?? '';
271
- if (!url.startsWith('http'))
272
- url = `${config.baseURL ?? ''}${url}`;
278
+ let url = config.url ?? "";
279
+ if (!url.startsWith("http"))
280
+ url = `${config.baseURL ?? ""}${url}`;
273
281
  addOrUpdateLog({
274
282
  id,
275
283
  url,