react-native-inapp-inspector 1.1.26 → 1.1.28
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/android/build.gradle +1 -0
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +34 -0
- package/dist/commonjs/components/ErrorBoundary.d.ts +1 -1
- package/dist/commonjs/components/ErrorBoundary.js +530 -100
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +176 -126
- package/dist/commonjs/components/Inspector/BundleTab.d.ts +1 -0
- package/dist/commonjs/components/Inspector/BundleTab.js +145 -21
- package/dist/commonjs/components/Inspector/CrashTab.js +0 -8
- package/dist/commonjs/components/Inspector/NetworkDetail.js +41 -0
- package/dist/commonjs/components/Inspector/PerformanceTab.d.ts +5 -0
- package/dist/commonjs/components/Inspector/PerformanceTab.js +588 -155
- package/dist/commonjs/components/Inspector/SettingsPanel.js +57 -22
- package/dist/commonjs/components/Inspector/TabBar.js +13 -1
- package/dist/commonjs/components/LogCard.js +75 -34
- package/dist/commonjs/components/NetworkIcons.d.ts +112 -102
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/analyticsLogger.d.ts +1 -11
- package/dist/commonjs/customHooks/analyticsLogger.js +8 -1
- package/dist/commonjs/customHooks/bundleAnalyzer.js +121 -124
- package/dist/commonjs/customHooks/networkLogger.d.ts +1 -0
- package/dist/commonjs/customHooks/networkLogger.js +16 -0
- package/dist/commonjs/customHooks/performanceTracker.d.ts +74 -0
- package/dist/commonjs/customHooks/performanceTracker.js +546 -392
- package/dist/commonjs/customHooks/reduxLogger.d.ts +1 -0
- package/dist/commonjs/customHooks/reduxLogger.js +3 -1
- package/dist/commonjs/helpers/index.js +27 -3
- package/dist/commonjs/i18n/locales/en.json +225 -4
- package/dist/commonjs/index.d.ts +1 -1
- package/dist/commonjs/index.js +36 -2
- package/dist/commonjs/styles/index.d.ts +3 -1
- package/dist/commonjs/styles/index.js +8 -6
- package/dist/commonjs/types/interfaces.d.ts +3 -0
- package/dist/esm/components/ErrorBoundary.d.ts +1 -1
- package/dist/esm/components/ErrorBoundary.js +498 -101
- package/dist/esm/components/Inspector/AnalyticsTab.js +177 -127
- package/dist/esm/components/Inspector/BundleTab.d.ts +1 -0
- package/dist/esm/components/Inspector/BundleTab.js +145 -23
- package/dist/esm/components/Inspector/CrashTab.js +0 -8
- package/dist/esm/components/Inspector/NetworkDetail.js +41 -0
- package/dist/esm/components/Inspector/PerformanceTab.d.ts +5 -0
- package/dist/esm/components/Inspector/PerformanceTab.js +591 -158
- package/dist/esm/components/Inspector/SettingsPanel.js +57 -22
- package/dist/esm/components/Inspector/TabBar.js +13 -1
- package/dist/esm/components/LogCard.js +75 -34
- package/dist/esm/components/NetworkIcons.d.ts +112 -102
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/analyticsLogger.d.ts +1 -11
- package/dist/esm/customHooks/analyticsLogger.js +6 -0
- package/dist/esm/customHooks/bundleAnalyzer.js +121 -124
- package/dist/esm/customHooks/networkLogger.d.ts +1 -0
- package/dist/esm/customHooks/networkLogger.js +16 -0
- package/dist/esm/customHooks/performanceTracker.d.ts +74 -0
- package/dist/esm/customHooks/performanceTracker.js +531 -391
- package/dist/esm/customHooks/reduxLogger.d.ts +1 -0
- package/dist/esm/customHooks/reduxLogger.js +1 -0
- package/dist/esm/helpers/index.js +27 -3
- package/dist/esm/i18n/locales/en.json +225 -4
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +24 -3
- package/dist/esm/styles/index.d.ts +3 -1
- package/dist/esm/styles/index.js +8 -6
- package/dist/esm/types/interfaces.d.ts +3 -0
- package/ios/NetworkInspectorModule.h +2 -0
- package/ios/NetworkInspectorModule.m +10 -0
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getCachedBundleAnalysis = exports.clearCachedBundleAnalysis = exports.analyzeHostAppBundle = exports.parseBundleSource = exports.trackRuntimeDefine = exports.trackRuntimeModuleExecution = exports.getHostScriptURL = void 0;
|
|
4
4
|
const AppColors_1 = require("../styles/AppColors");
|
|
5
|
+
const i18n_1 = require("../i18n");
|
|
5
6
|
// ─── Real Host App Bundle Analyzer ──────────────────────────────────────────
|
|
6
7
|
//
|
|
7
8
|
// Dynamically measures and analyzes the real JavaScript bundle and packages
|
|
@@ -254,25 +255,32 @@ const extractBundleModules = (bundleText) => {
|
|
|
254
255
|
const modules = [];
|
|
255
256
|
const seenIds = new Set();
|
|
256
257
|
if (bundleText && bundleText.length > 0) {
|
|
257
|
-
// Primary
|
|
258
|
-
const tailRegex = /\}\s*,\s*(\d+)\s*,\s
|
|
258
|
+
// 1. Primary Metro regex: matches }, <id>, [<deps>] or {<deps>}, "<path>"
|
|
259
|
+
const tailRegex = /\}\s*,\s*(\d+)\s*,\s*(?:\[[\s\S]*?\]|\{[\s\S]*?\})\s*,\s*(?:"([^"\r\n]+)"|'([^'\r\n]+)')/g;
|
|
259
260
|
let match;
|
|
260
261
|
while ((match = tailRegex.exec(bundleText)) !== null) {
|
|
261
262
|
const id = parseInt(match[1], 10);
|
|
262
|
-
const
|
|
263
|
-
const path = match[3] || match[4] || '';
|
|
264
|
-
const deps = depsStr
|
|
265
|
-
? depsStr
|
|
266
|
-
.split(',')
|
|
267
|
-
.map(s => parseInt(s.trim(), 10))
|
|
268
|
-
.filter(n => !isNaN(n))
|
|
269
|
-
: [];
|
|
263
|
+
const path = match[2] || match[3] || '';
|
|
270
264
|
if (!seenIds.has(id) && path.length > 0) {
|
|
271
265
|
seenIds.add(id);
|
|
272
|
-
modules.push({ id, deps, path });
|
|
266
|
+
modules.push({ id, deps: [], path });
|
|
273
267
|
}
|
|
274
268
|
}
|
|
275
|
-
//
|
|
269
|
+
// 2. SourceURL comment extraction (Metro dev server embeds //# sourceURL=... for every module)
|
|
270
|
+
const sourceUrlRegex = /\/\/[#@]\s*sourceURL=(?:https?:\/\/[^/\n\r]+\/|file:\/\/)?([^?\r\n#\s]+)/g;
|
|
271
|
+
let srcMatch;
|
|
272
|
+
let autoId = 900000;
|
|
273
|
+
while ((srcMatch = sourceUrlRegex.exec(bundleText)) !== null) {
|
|
274
|
+
const path = srcMatch[1];
|
|
275
|
+
if (path && path.length > 0 && !path.endsWith('.bundle')) {
|
|
276
|
+
const id = autoId++;
|
|
277
|
+
if (!seenIds.has(id)) {
|
|
278
|
+
seenIds.add(id);
|
|
279
|
+
modules.push({ id, deps: [], path });
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// 3. Fallback scan for __d calls
|
|
276
284
|
if (modules.length === 0) {
|
|
277
285
|
const defineRe = /__d\s*\(/g;
|
|
278
286
|
let m;
|
|
@@ -287,22 +295,13 @@ const extractBundleModules = (bundleText) => {
|
|
|
287
295
|
const idNum = parseInt(idMatch[1], 10);
|
|
288
296
|
if (seenIds.has(idNum))
|
|
289
297
|
continue;
|
|
290
|
-
const depsMatch = args[2].match(/\[([^\]]*)\]/);
|
|
291
|
-
const deps = [];
|
|
292
|
-
if (depsMatch) {
|
|
293
|
-
const depRe = /\d+/g;
|
|
294
|
-
let d;
|
|
295
|
-
while ((d = depRe.exec(depsMatch[1])) !== null) {
|
|
296
|
-
deps.push(parseInt(d[0], 10));
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
298
|
const pathRaw = args[3].trim();
|
|
300
299
|
const pathMatch = pathRaw.match(/^["']([^"']+)["']$/);
|
|
301
300
|
const path = pathMatch ? pathMatch[1] : pathRaw;
|
|
302
301
|
if (path.length === 0 || path.length > 500)
|
|
303
302
|
continue;
|
|
304
303
|
seenIds.add(idNum);
|
|
305
|
-
modules.push({ id: idNum, deps, path });
|
|
304
|
+
modules.push({ id: idNum, deps: [], path });
|
|
306
305
|
}
|
|
307
306
|
}
|
|
308
307
|
}
|
|
@@ -324,8 +323,28 @@ const getStaticStartupModuleIds = (bundleText) => {
|
|
|
324
323
|
}
|
|
325
324
|
return ids;
|
|
326
325
|
};
|
|
327
|
-
|
|
328
|
-
|
|
326
|
+
/**
|
|
327
|
+
* Dynamically computes the host app's project root directory without hardcoding any folder names.
|
|
328
|
+
* Uses node_modules boundary, root entry points (index/App/package.json), and common directory analysis.
|
|
329
|
+
*/
|
|
330
|
+
const detectProjectRoot = (allRawPaths) => {
|
|
331
|
+
const normPaths = allRawPaths.map(p => p.replace(/\\/g, '/'));
|
|
332
|
+
// 1. Extract from node_modules path (most definitive in Metro dev bundles)
|
|
333
|
+
for (const norm of normPaths) {
|
|
334
|
+
const nmIdx = norm.indexOf('/node_modules/');
|
|
335
|
+
if (nmIdx !== -1) {
|
|
336
|
+
return norm.slice(0, nmIdx + 1); // e.g. "/Users/user/Projects/my-app/"
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// 2. Extract from root entrypoint files (e.g. /path/to/project/index.js or App.tsx)
|
|
340
|
+
for (const norm of normPaths) {
|
|
341
|
+
const match = norm.match(/^(.*\/)(?:index\.[jt]sx?|app\.[jt]sx?|package\.json)(?:[?#].*)?$/i);
|
|
342
|
+
if (match && match[1]) {
|
|
343
|
+
return match[1];
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
// 3. Fallback: lowest common directory ancestor among all absolute project paths
|
|
347
|
+
const absPaths = normPaths.filter(p => p.startsWith('/') && !p.includes('/node_modules/'));
|
|
329
348
|
if (absPaths.length === 0)
|
|
330
349
|
return '';
|
|
331
350
|
if (absPaths.length === 1) {
|
|
@@ -333,20 +352,42 @@ const findCommonDirectoryPrefix = (paths) => {
|
|
|
333
352
|
return lastSlash > 0 ? absPaths[0].slice(0, lastSlash + 1) : '';
|
|
334
353
|
}
|
|
335
354
|
const splitPaths = absPaths.map(p => p.split('/'));
|
|
336
|
-
let
|
|
355
|
+
let commonLen = 0;
|
|
337
356
|
const first = splitPaths[0];
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
357
|
+
const minLen = Math.min(...splitPaths.map(sp => sp.length));
|
|
358
|
+
while (commonLen < minLen - 1) {
|
|
359
|
+
const seg = first[commonLen];
|
|
360
|
+
if (splitPaths.every(sp => sp[commonLen] === seg)) {
|
|
361
|
+
commonLen++;
|
|
342
362
|
}
|
|
343
363
|
else {
|
|
344
364
|
break;
|
|
345
365
|
}
|
|
346
366
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
367
|
+
return commonLen > 0 ? first.slice(0, commonLen).join('/') + '/' : '';
|
|
368
|
+
};
|
|
369
|
+
/**
|
|
370
|
+
* Normalizes absolute or relative module paths so they retain their full
|
|
371
|
+
* folder hierarchy from the host project root dynamically.
|
|
372
|
+
*/
|
|
373
|
+
const normalizeProjectRelativePath = (rawPath, projectRoot) => {
|
|
374
|
+
let clean = rawPath.replace(/\\/g, '/');
|
|
375
|
+
// Strip query parameters e.g. ?platform=ios or hashes
|
|
376
|
+
const qIdx = clean.search(/[?#]/);
|
|
377
|
+
if (qIdx !== -1) {
|
|
378
|
+
clean = clean.slice(0, qIdx);
|
|
379
|
+
}
|
|
380
|
+
// Strip file:// or http://.../ dev server URL prefixes
|
|
381
|
+
clean = clean.replace(/^(?:https?:\/\/[^/]+\/|file:\/\/)/, '');
|
|
382
|
+
// Strip dynamically detected project root prefix
|
|
383
|
+
if (projectRoot && clean.startsWith(projectRoot)) {
|
|
384
|
+
clean = clean.slice(projectRoot.length);
|
|
385
|
+
}
|
|
386
|
+
// Clean leading ../ sequences, ./, and leading /
|
|
387
|
+
clean = clean.replace(/^(\.\.\/)+/, '').replace(/^\.\//, '').replace(/^\/+/, '');
|
|
388
|
+
if (!clean)
|
|
389
|
+
clean = rawPath.split('/').pop() || rawPath;
|
|
390
|
+
return clean;
|
|
350
391
|
};
|
|
351
392
|
const isExternalPackage = (rawPath) => {
|
|
352
393
|
// 1. Standard node_modules
|
|
@@ -457,19 +498,12 @@ const parseBundleSource = (bundleText, totalBytes, scriptURL, isLive = true) =>
|
|
|
457
498
|
}
|
|
458
499
|
rawProjectItems.push({ mod, rawPath });
|
|
459
500
|
}
|
|
460
|
-
//
|
|
461
|
-
const
|
|
501
|
+
// Dynamically calculate project root prefix to cleanly extract all host app folders & files
|
|
502
|
+
const projectRoot = detectProjectRoot(modules.map(item => item.path));
|
|
462
503
|
const discoveredFiles = [];
|
|
463
504
|
let fileIdx = 0;
|
|
464
505
|
for (const { mod, rawPath } of rawProjectItems) {
|
|
465
|
-
|
|
466
|
-
if (commonPrefix && cleanPath.startsWith(commonPrefix)) {
|
|
467
|
-
cleanPath = cleanPath.slice(commonPrefix.length);
|
|
468
|
-
}
|
|
469
|
-
// Clean leading ../ sequences, ./, and leading /
|
|
470
|
-
cleanPath = cleanPath.replace(/^(\.\.\/)+/, '').replace(/^\.\//, '').replace(/^\/+/, '');
|
|
471
|
-
if (!cleanPath)
|
|
472
|
-
cleanPath = rawPath.split('/').pop() || rawPath;
|
|
506
|
+
const cleanPath = normalizeProjectRelativePath(rawPath, projectRoot);
|
|
473
507
|
const isLocalFile = cleanPath.endsWith('.tsx') ||
|
|
474
508
|
cleanPath.endsWith('.ts') ||
|
|
475
509
|
cleanPath.endsWith('.jsx') ||
|
|
@@ -543,43 +577,6 @@ const parseBundleSource = (bundleText, totalBytes, scriptURL, isLive = true) =>
|
|
|
543
577
|
isConsumed,
|
|
544
578
|
});
|
|
545
579
|
}
|
|
546
|
-
// If no modules could be parsed (e.g. Hermes bytecode / obfuscated bundle), synthesize from loaded modules
|
|
547
|
-
if (discoveredFiles.length === 0) {
|
|
548
|
-
discoveredFiles.push({
|
|
549
|
-
id: 'hf-1',
|
|
550
|
-
name: 'index.js (App Entry)',
|
|
551
|
-
path: 'index.js',
|
|
552
|
-
ext: 'JS',
|
|
553
|
-
category: 'javascript',
|
|
554
|
-
sizeKb: Math.round(totalDevKb * 0.08),
|
|
555
|
-
meta: 'React Native Root Entrypoint',
|
|
556
|
-
color: AppColors_1.AppColors.indigo500,
|
|
557
|
-
status: 'optimal',
|
|
558
|
-
isConsumed: true,
|
|
559
|
-
}, {
|
|
560
|
-
id: 'hf-2',
|
|
561
|
-
name: 'App.tsx',
|
|
562
|
-
path: 'src/App.tsx',
|
|
563
|
-
ext: 'TSX',
|
|
564
|
-
category: 'typescript',
|
|
565
|
-
sizeKb: Math.round(totalDevKb * 0.12),
|
|
566
|
-
meta: 'Root Navigation & Provider Container',
|
|
567
|
-
color: AppColors_1.AppColors.sky500,
|
|
568
|
-
status: 'optimal',
|
|
569
|
-
isConsumed: true,
|
|
570
|
-
}, {
|
|
571
|
-
id: 'hf-3',
|
|
572
|
-
name: 'HomeScreen.tsx',
|
|
573
|
-
path: 'src/screens/HomeScreen.tsx',
|
|
574
|
-
ext: 'TSX',
|
|
575
|
-
category: 'typescript',
|
|
576
|
-
sizeKb: Math.round(totalDevKb * 0.06),
|
|
577
|
-
meta: 'Main Dashboard Screen View',
|
|
578
|
-
color: AppColors_1.AppColors.sky500,
|
|
579
|
-
status: 'optimal',
|
|
580
|
-
isConsumed: true,
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
580
|
// Dynamic color palette generator based on package name hash
|
|
584
581
|
const getPackageColor = (name) => {
|
|
585
582
|
const colors = [
|
|
@@ -732,105 +729,105 @@ const parseBundleSource = (bundleText, totalBytes, scriptURL, isLive = true) =>
|
|
|
732
729
|
const iosComponents = [
|
|
733
730
|
{
|
|
734
731
|
id: 'ios-c1',
|
|
735
|
-
name:
|
|
732
|
+
name: (0, i18n_1.t)('bundle.iosComp1Name'),
|
|
736
733
|
category: 'frameworks',
|
|
737
734
|
sizeMb: nativeFrameworksMb,
|
|
738
735
|
pct: Number(((nativeFrameworksMb / iosInstallMb) * 100).toFixed(1)),
|
|
739
736
|
color: AppColors_1.AppColors.indigo500,
|
|
740
|
-
description:
|
|
741
|
-
advice:
|
|
737
|
+
description: (0, i18n_1.t)('bundle.iosComp1Desc', { count: packagesList.length }),
|
|
738
|
+
advice: (0, i18n_1.t)('bundle.iosComp1Advice'),
|
|
742
739
|
},
|
|
743
740
|
{
|
|
744
741
|
id: 'ios-c2',
|
|
745
|
-
name:
|
|
742
|
+
name: (0, i18n_1.t)('bundle.iosComp2Name'),
|
|
746
743
|
category: 'native',
|
|
747
744
|
sizeMb: nativeMachoMb,
|
|
748
745
|
pct: Number(((nativeMachoMb / iosInstallMb) * 100).toFixed(1)),
|
|
749
746
|
color: AppColors_1.AppColors.sky500,
|
|
750
|
-
description:
|
|
751
|
-
advice:
|
|
747
|
+
description: (0, i18n_1.t)('bundle.iosComp2Desc'),
|
|
748
|
+
advice: (0, i18n_1.t)('bundle.iosComp2Advice'),
|
|
752
749
|
},
|
|
753
750
|
{
|
|
754
751
|
id: 'ios-c3',
|
|
755
|
-
name:
|
|
752
|
+
name: (0, i18n_1.t)('bundle.iosComp3Name'),
|
|
756
753
|
category: 'assets',
|
|
757
754
|
sizeMb: assetsCatalogMb,
|
|
758
755
|
pct: Number(((assetsCatalogMb / iosInstallMb) * 100).toFixed(1)),
|
|
759
756
|
color: AppColors_1.AppColors.pink500,
|
|
760
|
-
description:
|
|
761
|
-
advice:
|
|
757
|
+
description: (0, i18n_1.t)('bundle.iosComp3Desc'),
|
|
758
|
+
advice: (0, i18n_1.t)('bundle.iosComp3Advice'),
|
|
762
759
|
},
|
|
763
760
|
{
|
|
764
761
|
id: 'ios-c4',
|
|
765
|
-
name:
|
|
762
|
+
name: (0, i18n_1.t)('bundle.iosComp4Name'),
|
|
766
763
|
category: 'js',
|
|
767
764
|
sizeMb: releaseJsMb,
|
|
768
765
|
pct: Number(((releaseJsMb / iosInstallMb) * 100).toFixed(1)),
|
|
769
766
|
color: AppColors_1.AppColors.emerald500,
|
|
770
|
-
description:
|
|
771
|
-
advice:
|
|
767
|
+
description: (0, i18n_1.t)('bundle.iosComp4Desc', { count: discoveredFiles.length }),
|
|
768
|
+
advice: (0, i18n_1.t)('bundle.iosComp4Advice'),
|
|
772
769
|
},
|
|
773
770
|
{
|
|
774
771
|
id: 'ios-c5',
|
|
775
|
-
name:
|
|
772
|
+
name: (0, i18n_1.t)('bundle.iosComp5Name'),
|
|
776
773
|
category: 'meta',
|
|
777
774
|
sizeMb: metadataMb,
|
|
778
775
|
pct: Number(((metadataMb / iosInstallMb) * 100).toFixed(1)),
|
|
779
776
|
color: AppColors_1.AppColors.amber500,
|
|
780
|
-
description:
|
|
781
|
-
advice:
|
|
777
|
+
description: (0, i18n_1.t)('bundle.iosComp5Desc'),
|
|
778
|
+
advice: (0, i18n_1.t)('bundle.iosComp5Advice'),
|
|
782
779
|
},
|
|
783
780
|
];
|
|
784
781
|
const androidComponents = [
|
|
785
782
|
{
|
|
786
783
|
id: 'and-c1',
|
|
787
|
-
name:
|
|
784
|
+
name: (0, i18n_1.t)('bundle.andComp1Name'),
|
|
788
785
|
category: 'native',
|
|
789
786
|
sizeMb: androidCppMb,
|
|
790
787
|
pct: Number(((androidCppMb / androidInstallMb) * 100).toFixed(1)),
|
|
791
788
|
color: AppColors_1.AppColors.sky500,
|
|
792
|
-
description:
|
|
793
|
-
advice:
|
|
789
|
+
description: (0, i18n_1.t)('bundle.andComp1Desc', { count: packagesList.length }),
|
|
790
|
+
advice: (0, i18n_1.t)('bundle.andComp1Advice'),
|
|
794
791
|
},
|
|
795
792
|
{
|
|
796
793
|
id: 'and-c2',
|
|
797
|
-
name:
|
|
794
|
+
name: (0, i18n_1.t)('bundle.andComp2Name'),
|
|
798
795
|
category: 'frameworks',
|
|
799
796
|
sizeMb: androidDexMb,
|
|
800
797
|
pct: Number(((androidDexMb / androidInstallMb) * 100).toFixed(1)),
|
|
801
798
|
color: AppColors_1.AppColors.indigo500,
|
|
802
|
-
description:
|
|
803
|
-
advice:
|
|
799
|
+
description: (0, i18n_1.t)('bundle.andComp2Desc'),
|
|
800
|
+
advice: (0, i18n_1.t)('bundle.andComp2Advice'),
|
|
804
801
|
},
|
|
805
802
|
{
|
|
806
803
|
id: 'and-c3',
|
|
807
|
-
name:
|
|
804
|
+
name: (0, i18n_1.t)('bundle.andComp3Name'),
|
|
808
805
|
category: 'assets',
|
|
809
806
|
sizeMb: androidResMb,
|
|
810
807
|
pct: Number(((androidResMb / androidInstallMb) * 100).toFixed(1)),
|
|
811
808
|
color: AppColors_1.AppColors.pink500,
|
|
812
|
-
description:
|
|
813
|
-
advice:
|
|
809
|
+
description: (0, i18n_1.t)('bundle.andComp3Desc'),
|
|
810
|
+
advice: (0, i18n_1.t)('bundle.andComp3Advice'),
|
|
814
811
|
},
|
|
815
812
|
{
|
|
816
813
|
id: 'and-c4',
|
|
817
|
-
name:
|
|
814
|
+
name: (0, i18n_1.t)('bundle.andComp4Name'),
|
|
818
815
|
category: 'js',
|
|
819
816
|
sizeMb: releaseJsMb,
|
|
820
817
|
pct: Number(((releaseJsMb / androidInstallMb) * 100).toFixed(1)),
|
|
821
818
|
color: AppColors_1.AppColors.emerald500,
|
|
822
|
-
description:
|
|
823
|
-
advice:
|
|
819
|
+
description: (0, i18n_1.t)('bundle.andComp4Desc', { count: discoveredFiles.length }),
|
|
820
|
+
advice: (0, i18n_1.t)('bundle.andComp4Advice'),
|
|
824
821
|
},
|
|
825
822
|
{
|
|
826
823
|
id: 'and-c5',
|
|
827
|
-
name:
|
|
824
|
+
name: (0, i18n_1.t)('bundle.andComp5Name'),
|
|
828
825
|
category: 'meta',
|
|
829
826
|
sizeMb: 2.6,
|
|
830
827
|
pct: Number(((2.6 / androidInstallMb) * 100).toFixed(1)),
|
|
831
828
|
color: AppColors_1.AppColors.amber500,
|
|
832
|
-
description:
|
|
833
|
-
advice:
|
|
829
|
+
description: (0, i18n_1.t)('bundle.andComp5Desc'),
|
|
830
|
+
advice: (0, i18n_1.t)('bundle.andComp5Advice'),
|
|
834
831
|
},
|
|
835
832
|
];
|
|
836
833
|
// Universal Standalone APK metrics (Multi-ABI FAT APK: arm64 + v7a + x86_64)
|
|
@@ -840,53 +837,53 @@ const parseBundleSource = (bundleText, totalBytes, scriptURL, isLive = true) =>
|
|
|
840
837
|
const androidApkComponents = [
|
|
841
838
|
{
|
|
842
839
|
id: 'apk-c1',
|
|
843
|
-
name:
|
|
840
|
+
name: (0, i18n_1.t)('bundle.apkComp1Name'),
|
|
844
841
|
category: 'native',
|
|
845
842
|
sizeMb: androidMultiAbiCppMb,
|
|
846
843
|
pct: Number(((androidMultiAbiCppMb / androidApkInstallMb) * 100).toFixed(1)),
|
|
847
844
|
color: AppColors_1.AppColors.sky500,
|
|
848
|
-
description:
|
|
849
|
-
advice:
|
|
845
|
+
description: (0, i18n_1.t)('bundle.apkComp1Desc'),
|
|
846
|
+
advice: (0, i18n_1.t)('bundle.apkComp1Advice'),
|
|
850
847
|
},
|
|
851
848
|
{
|
|
852
849
|
id: 'apk-c2',
|
|
853
|
-
name:
|
|
850
|
+
name: (0, i18n_1.t)('bundle.apkComp2Name'),
|
|
854
851
|
category: 'frameworks',
|
|
855
852
|
sizeMb: androidDexMb,
|
|
856
853
|
pct: Number(((androidDexMb / androidApkInstallMb) * 100).toFixed(1)),
|
|
857
854
|
color: AppColors_1.AppColors.indigo500,
|
|
858
|
-
description:
|
|
859
|
-
advice:
|
|
855
|
+
description: (0, i18n_1.t)('bundle.apkComp2Desc'),
|
|
856
|
+
advice: (0, i18n_1.t)('bundle.apkComp2Advice'),
|
|
860
857
|
},
|
|
861
858
|
{
|
|
862
859
|
id: 'apk-c3',
|
|
863
|
-
name:
|
|
860
|
+
name: (0, i18n_1.t)('bundle.apkComp3Name'),
|
|
864
861
|
category: 'assets',
|
|
865
862
|
sizeMb: androidResMb,
|
|
866
863
|
pct: Number(((androidResMb / androidApkInstallMb) * 100).toFixed(1)),
|
|
867
864
|
color: AppColors_1.AppColors.pink500,
|
|
868
|
-
description:
|
|
869
|
-
advice:
|
|
865
|
+
description: (0, i18n_1.t)('bundle.apkComp3Desc'),
|
|
866
|
+
advice: (0, i18n_1.t)('bundle.apkComp3Advice'),
|
|
870
867
|
},
|
|
871
868
|
{
|
|
872
869
|
id: 'apk-c4',
|
|
873
|
-
name:
|
|
870
|
+
name: (0, i18n_1.t)('bundle.apkComp4Name'),
|
|
874
871
|
category: 'js',
|
|
875
872
|
sizeMb: releaseJsMb,
|
|
876
873
|
pct: Number(((releaseJsMb / androidApkInstallMb) * 100).toFixed(1)),
|
|
877
874
|
color: AppColors_1.AppColors.emerald500,
|
|
878
|
-
description:
|
|
879
|
-
advice:
|
|
875
|
+
description: (0, i18n_1.t)('bundle.apkComp4Desc', { count: discoveredFiles.length }),
|
|
876
|
+
advice: (0, i18n_1.t)('bundle.apkComp4Advice'),
|
|
880
877
|
},
|
|
881
878
|
{
|
|
882
879
|
id: 'apk-c5',
|
|
883
|
-
name:
|
|
880
|
+
name: (0, i18n_1.t)('bundle.apkComp5Name'),
|
|
884
881
|
category: 'meta',
|
|
885
882
|
sizeMb: 3.2,
|
|
886
883
|
pct: Number(((3.2 / androidApkInstallMb) * 100).toFixed(1)),
|
|
887
884
|
color: AppColors_1.AppColors.amber500,
|
|
888
|
-
description:
|
|
889
|
-
advice:
|
|
885
|
+
description: (0, i18n_1.t)('bundle.apkComp5Desc'),
|
|
886
|
+
advice: (0, i18n_1.t)('bundle.apkComp5Advice'),
|
|
890
887
|
},
|
|
891
888
|
];
|
|
892
889
|
return {
|
|
@@ -154,15 +154,26 @@ const setupNetworkLogger = () => {
|
|
|
154
154
|
return originalFetch(url, options);
|
|
155
155
|
let caller = "Unknown";
|
|
156
156
|
let requestHeaders;
|
|
157
|
+
let client = 'fetch';
|
|
157
158
|
try {
|
|
158
159
|
requestHeaders = normaliseHeaders(options?.headers);
|
|
159
160
|
caller = getCallerFromStack(); // ✅ Capture call line
|
|
161
|
+
if (requestHeaders?.['apollographql-client-name'] || finalUrl?.toLowerCase().includes('/graphql')) {
|
|
162
|
+
client = 'apollo';
|
|
163
|
+
}
|
|
164
|
+
else if (requestHeaders?.['x-requested-with']?.toLowerCase().includes('xmlhttprequest')) {
|
|
165
|
+
client = 'xhr';
|
|
166
|
+
}
|
|
167
|
+
else if (caller?.toLowerCase().includes('axios')) {
|
|
168
|
+
client = 'axios';
|
|
169
|
+
}
|
|
160
170
|
addOrUpdateLog({
|
|
161
171
|
id,
|
|
162
172
|
url: finalUrl,
|
|
163
173
|
method,
|
|
164
174
|
startTime: start,
|
|
165
175
|
caller,
|
|
176
|
+
client,
|
|
166
177
|
request: method === "GET" ? undefined : parseRequestData(options?.body),
|
|
167
178
|
requestHeaders,
|
|
168
179
|
});
|
|
@@ -202,6 +213,7 @@ const setupNetworkLogger = () => {
|
|
|
202
213
|
duration,
|
|
203
214
|
startTime: start,
|
|
204
215
|
caller,
|
|
216
|
+
client,
|
|
205
217
|
responseHeaders,
|
|
206
218
|
});
|
|
207
219
|
}
|
|
@@ -218,6 +230,7 @@ const setupNetworkLogger = () => {
|
|
|
218
230
|
startTime: start,
|
|
219
231
|
response: error,
|
|
220
232
|
caller,
|
|
233
|
+
client,
|
|
221
234
|
duration: Date.now() - start,
|
|
222
235
|
});
|
|
223
236
|
}
|
|
@@ -274,6 +287,7 @@ const addAxiosInterceptors = (axiosInstance) => {
|
|
|
274
287
|
method,
|
|
275
288
|
startTime: start,
|
|
276
289
|
caller,
|
|
290
|
+
client: 'axios',
|
|
277
291
|
request: method === "GET" ? undefined : parseRequestData(config.data),
|
|
278
292
|
requestHeaders: normaliseHeaders(config.headers),
|
|
279
293
|
});
|
|
@@ -299,6 +313,7 @@ const addAxiosInterceptors = (axiosInstance) => {
|
|
|
299
313
|
startTime: start || Date.now(),
|
|
300
314
|
duration: start != null ? Date.now() - start : undefined,
|
|
301
315
|
caller,
|
|
316
|
+
client: 'axios',
|
|
302
317
|
responseHeaders: normaliseHeaders(response.headers),
|
|
303
318
|
});
|
|
304
319
|
return response;
|
|
@@ -321,6 +336,7 @@ const addAxiosInterceptors = (axiosInstance) => {
|
|
|
321
336
|
startTime: start || Date.now(),
|
|
322
337
|
duration: start != null ? Date.now() - start : undefined,
|
|
323
338
|
caller,
|
|
339
|
+
client: 'axios',
|
|
324
340
|
responseHeaders: normaliseHeaders(error.response?.headers),
|
|
325
341
|
});
|
|
326
342
|
}
|
|
@@ -5,6 +5,11 @@ export interface PerformanceEvent {
|
|
|
5
5
|
category: 'render' | 'navigation' | 'memory' | 'io' | 'bridge';
|
|
6
6
|
fps: number;
|
|
7
7
|
durationMs: number;
|
|
8
|
+
droppedFrames?: number;
|
|
9
|
+
frameTimeMs?: number;
|
|
10
|
+
frameBudgetPct?: number;
|
|
11
|
+
bottleneckThread?: 'JS Thread' | 'UI Thread' | 'Bridge' | 'Balanced';
|
|
12
|
+
screenName?: string;
|
|
8
13
|
label: string;
|
|
9
14
|
detail: string;
|
|
10
15
|
source?: string;
|
|
@@ -54,7 +59,76 @@ export interface ComponentRenderProfile {
|
|
|
54
59
|
fixKeys: PerformanceFixKey[];
|
|
55
60
|
severity: 'optimal' | 'warning' | 'critical';
|
|
56
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Dynamically generates tailored Before/After performance optimization code snippets
|
|
64
|
+
* based on the target component's real identifier, props, and detected anti-pattern.
|
|
65
|
+
*/
|
|
66
|
+
export declare const generateFixSnippet: (fixKey: string, componentName?: string, context?: {
|
|
67
|
+
propName?: string;
|
|
68
|
+
actionName?: string;
|
|
69
|
+
itemHeight?: number;
|
|
70
|
+
}) => PerformanceFixKey;
|
|
71
|
+
/**
|
|
72
|
+
* Dynamically resolves caller file path or runtime source from the active JavaScript stack trace.
|
|
73
|
+
* Does not assume fixed directory hierarchies (such as src/ or components/) and extracts
|
|
74
|
+
* whatever relative path or symbol the host project structure uses.
|
|
75
|
+
*/
|
|
76
|
+
export declare function getCallerSourceFile(fallbackName?: string): string;
|
|
77
|
+
export declare const getInitialRenderProfiles: () => ComponentRenderProfile[];
|
|
78
|
+
export declare const getInitialPerformanceEvents: () => PerformanceEvent[];
|
|
57
79
|
export declare const INITIAL_EVENTS: PerformanceEvent[];
|
|
80
|
+
export declare const subscribeRenderProfiles: (listener: (profiles: ComponentRenderProfile[]) => void) => () => void;
|
|
81
|
+
export declare const getRenderProfiles: () => ComponentRenderProfile[];
|
|
82
|
+
export declare const registerComponentProfile: (profile: ComponentRenderProfile) => void;
|
|
83
|
+
export declare const trackComponentRender: (params: {
|
|
84
|
+
name: string;
|
|
85
|
+
type?: ComponentRenderProfile["type"];
|
|
86
|
+
sourceFile?: string;
|
|
87
|
+
renderTimeMs?: number;
|
|
88
|
+
isWasteful?: boolean;
|
|
89
|
+
reason?: string;
|
|
90
|
+
fixKeys?: PerformanceFixKey[];
|
|
91
|
+
}) => void;
|
|
92
|
+
/**
|
|
93
|
+
* Dynamically queries Hermes or JavaScript runtime memory statistics.
|
|
94
|
+
*/
|
|
95
|
+
export declare const getHermesMemoryStats: () => LiveMemoryStats;
|
|
96
|
+
/**
|
|
97
|
+
* Dynamically records and evaluates screen navigation transition performance.
|
|
98
|
+
*/
|
|
99
|
+
export declare const trackNavigationTransition: (screenName: string, durationMs: number, options?: {
|
|
100
|
+
ttiMs?: number;
|
|
101
|
+
droppedFrames?: number;
|
|
102
|
+
source?: string;
|
|
103
|
+
}) => PerformanceEvent;
|
|
104
|
+
/**
|
|
105
|
+
* React Hook that automatically profiles screen mounts and navigation transitions.
|
|
106
|
+
*/
|
|
107
|
+
export declare const useNavigationProfiler: (screenName: string, options?: {
|
|
108
|
+
onTransitionEnd?: (durationMs: number) => void;
|
|
109
|
+
}) => void;
|
|
110
|
+
/**
|
|
111
|
+
* Measures synchronous execution duration and alerts on frame budget spikes (>16ms).
|
|
112
|
+
*/
|
|
113
|
+
export declare const trackHeavyTask: <T>(taskName: string, syncFn: () => T, options?: {
|
|
114
|
+
thresholdMs?: number;
|
|
115
|
+
source?: string;
|
|
116
|
+
}) => T;
|
|
117
|
+
/**
|
|
118
|
+
* Measures async operation / Promise latency and records slow network or disk tasks.
|
|
119
|
+
*/
|
|
120
|
+
export declare const measureAsync: <T>(taskName: string, asyncFn: () => Promise<T>, options?: {
|
|
121
|
+
thresholdMs?: number;
|
|
122
|
+
source?: string;
|
|
123
|
+
}) => Promise<T>;
|
|
124
|
+
/**
|
|
125
|
+
* Custom React Hook to profile any component or screen renders dynamically in runtime.
|
|
126
|
+
*/
|
|
127
|
+
export declare const useComponentProfiler: (componentName: string, options?: {
|
|
128
|
+
type?: ComponentRenderProfile["type"];
|
|
129
|
+
sourceFile?: string;
|
|
130
|
+
propsToCompare?: Record<string, any>;
|
|
131
|
+
}) => void;
|
|
58
132
|
export declare const usePerformanceTracker: () => {
|
|
59
133
|
isRecording: boolean;
|
|
60
134
|
setIsRecording: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|