@rn-ave/core 0.1.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/README.md +31 -0
- package/dist/appRegistry.d.ts +11 -0
- package/dist/appRegistry.js +52 -0
- package/dist/auto.d.ts +15 -0
- package/dist/auto.js +35 -0
- package/dist/components/InspectorButton.d.ts +7 -0
- package/dist/components/InspectorButton.js +125 -0
- package/dist/components/InspectorOverlay.d.ts +11 -0
- package/dist/components/InspectorOverlay.js +60 -0
- package/dist/context/extractor.d.ts +7 -0
- package/dist/context/extractor.js +235 -0
- package/dist/context/formatter.d.ts +13 -0
- package/dist/context/formatter.js +95 -0
- package/dist/devMenu.d.ts +26 -0
- package/dist/devMenu.js +80 -0
- package/dist/editor.d.ts +20 -0
- package/dist/editor.js +93 -0
- package/dist/fiber/hook.d.ts +18 -0
- package/dist/fiber/hook.js +103 -0
- package/dist/fiber/source.d.ts +21 -0
- package/dist/fiber/source.js +94 -0
- package/dist/fiber/traversal.d.ts +27 -0
- package/dist/fiber/traversal.js +163 -0
- package/dist/gesture/detector.d.ts +17 -0
- package/dist/gesture/detector.js +84 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8 -0
- package/dist/overlay/highlight.d.ts +14 -0
- package/dist/overlay/highlight.js +177 -0
- package/dist/overlay/tooltip.d.ts +15 -0
- package/dist/overlay/tooltip.js +467 -0
- package/dist/provider.d.ts +10 -0
- package/dist/provider.js +264 -0
- package/dist/types.d.ts +94 -0
- package/dist/types.js +2 -0
- package/package.json +58 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatForAgent = formatForAgent;
|
|
4
|
+
exports.formatCompact = formatCompact;
|
|
5
|
+
exports.formatForTerminal = formatForTerminal;
|
|
6
|
+
const source_1 = require("../fiber/source");
|
|
7
|
+
/**
|
|
8
|
+
* Formats extracted context as markdown for AI agents
|
|
9
|
+
*/
|
|
10
|
+
function formatForAgent(context) {
|
|
11
|
+
const lines = [];
|
|
12
|
+
lines.push(`## Selected Component: ${context.componentName}`);
|
|
13
|
+
lines.push('');
|
|
14
|
+
// File location
|
|
15
|
+
if (context.source) {
|
|
16
|
+
lines.push(`### File`);
|
|
17
|
+
lines.push(`\`${(0, source_1.formatSourceLocation)(context.source)}\``);
|
|
18
|
+
lines.push('');
|
|
19
|
+
}
|
|
20
|
+
// Component hierarchy
|
|
21
|
+
if (context.componentHierarchy.length > 0) {
|
|
22
|
+
lines.push(`### Component Hierarchy`);
|
|
23
|
+
lines.push('```');
|
|
24
|
+
context.componentHierarchy.forEach((name, i) => {
|
|
25
|
+
const indent = ' '.repeat(i);
|
|
26
|
+
lines.push(`${indent}<${name}>`);
|
|
27
|
+
});
|
|
28
|
+
lines.push('```');
|
|
29
|
+
lines.push('');
|
|
30
|
+
}
|
|
31
|
+
// Props
|
|
32
|
+
if (Object.keys(context.props).length > 0) {
|
|
33
|
+
lines.push(`### Props`);
|
|
34
|
+
lines.push('```json');
|
|
35
|
+
lines.push(JSON.stringify(context.props, null, 2));
|
|
36
|
+
lines.push('```');
|
|
37
|
+
lines.push('');
|
|
38
|
+
}
|
|
39
|
+
// JSX Preview
|
|
40
|
+
lines.push(`### JSX Preview`);
|
|
41
|
+
lines.push('```jsx');
|
|
42
|
+
lines.push(context.jsxPreview);
|
|
43
|
+
lines.push('```');
|
|
44
|
+
lines.push('');
|
|
45
|
+
lines.push('---');
|
|
46
|
+
lines.push(`*Captured at ${new Date(context.timestamp).toLocaleTimeString()}*`);
|
|
47
|
+
return lines.join('\n');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Formats context as compact single-line (for clipboard)
|
|
51
|
+
*/
|
|
52
|
+
function formatCompact(context) {
|
|
53
|
+
const parts = [];
|
|
54
|
+
parts.push(context.componentName);
|
|
55
|
+
if (context.source) {
|
|
56
|
+
parts.push(`at ${(0, source_1.formatSourceLocation)(context.source)}`);
|
|
57
|
+
}
|
|
58
|
+
if (context.componentHierarchy.length > 1) {
|
|
59
|
+
parts.push(`in ${context.componentHierarchy[context.componentHierarchy.length - 1]}`);
|
|
60
|
+
}
|
|
61
|
+
return parts.join(' ');
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Formats context for terminal/console output
|
|
65
|
+
*/
|
|
66
|
+
function formatForTerminal(context) {
|
|
67
|
+
const lines = [];
|
|
68
|
+
const divider = '─'.repeat(50);
|
|
69
|
+
lines.push('');
|
|
70
|
+
lines.push(`┌${divider}┐`);
|
|
71
|
+
lines.push(`│ 🔍 RN-AVE: ${context.componentName.padEnd(32)} │`);
|
|
72
|
+
lines.push(`├${divider}┤`);
|
|
73
|
+
if (context.source) {
|
|
74
|
+
lines.push(`│ 📁 ${(0, source_1.formatSourceLocation)(context.source).padEnd(45)} │`);
|
|
75
|
+
}
|
|
76
|
+
if (context.componentHierarchy.length > 0) {
|
|
77
|
+
const hierarchy = context.componentHierarchy.slice(0, 5).join(' → ');
|
|
78
|
+
lines.push(`│ 🏗️ ${hierarchy.substring(0, 44).padEnd(44)} │`);
|
|
79
|
+
}
|
|
80
|
+
if (Object.keys(context.props).length > 0) {
|
|
81
|
+
lines.push(`├${divider}┤`);
|
|
82
|
+
lines.push(`│ Props:${' '.repeat(42)} │`);
|
|
83
|
+
const propsStr = JSON.stringify(context.props, null, 2);
|
|
84
|
+
propsStr.split('\n').slice(0, 6).forEach(line => {
|
|
85
|
+
const trimmed = line.substring(0, 46);
|
|
86
|
+
lines.push(`│ ${trimmed.padEnd(46)} │`);
|
|
87
|
+
});
|
|
88
|
+
if (propsStr.split('\n').length > 6) {
|
|
89
|
+
lines.push(`│ ...${' '.repeat(43)} │`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
lines.push(`└${divider}┘`);
|
|
93
|
+
lines.push('');
|
|
94
|
+
return lines.join('\n');
|
|
95
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev Menu Integration for React Native and Expo
|
|
3
|
+
* Adds "Toggle Inspector" to the development menu
|
|
4
|
+
*
|
|
5
|
+
* Works with:
|
|
6
|
+
* - React Native CLI: Shake or Cmd+D (iOS) / Cmd+M (Android)
|
|
7
|
+
* - Expo Dev Client: Shake or three-finger long press
|
|
8
|
+
* - Expo Go: Shake gesture
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Register the inspector toggle in the dev menu
|
|
12
|
+
* Call this once when the Inspector component mounts
|
|
13
|
+
*/
|
|
14
|
+
export declare function registerDevMenuToggle(onToggle: () => void): void;
|
|
15
|
+
/**
|
|
16
|
+
* Update the toggle callback (when component re-renders)
|
|
17
|
+
*/
|
|
18
|
+
export declare function updateDevMenuCallback(onToggle: () => void): void;
|
|
19
|
+
/**
|
|
20
|
+
* Check if dev menu is available
|
|
21
|
+
*/
|
|
22
|
+
export declare function isDevMenuAvailable(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Instructions for opening dev menu on different platforms
|
|
25
|
+
*/
|
|
26
|
+
export declare function getDevMenuInstructions(): string;
|
package/dist/devMenu.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Dev Menu Integration for React Native and Expo
|
|
4
|
+
* Adds "Toggle Inspector" to the development menu
|
|
5
|
+
*
|
|
6
|
+
* Works with:
|
|
7
|
+
* - React Native CLI: Shake or Cmd+D (iOS) / Cmd+M (Android)
|
|
8
|
+
* - Expo Dev Client: Shake or three-finger long press
|
|
9
|
+
* - Expo Go: Shake gesture
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.registerDevMenuToggle = registerDevMenuToggle;
|
|
13
|
+
exports.updateDevMenuCallback = updateDevMenuCallback;
|
|
14
|
+
exports.isDevMenuAvailable = isDevMenuAvailable;
|
|
15
|
+
exports.getDevMenuInstructions = getDevMenuInstructions;
|
|
16
|
+
const react_native_1 = require("react-native");
|
|
17
|
+
let isRegistered = false;
|
|
18
|
+
let toggleCallback = null;
|
|
19
|
+
/**
|
|
20
|
+
* Register the inspector toggle in the dev menu
|
|
21
|
+
* Call this once when the Inspector component mounts
|
|
22
|
+
*/
|
|
23
|
+
function registerDevMenuToggle(onToggle) {
|
|
24
|
+
if (typeof __DEV__ === 'undefined' || !__DEV__)
|
|
25
|
+
return;
|
|
26
|
+
toggleCallback = onToggle;
|
|
27
|
+
if (isRegistered)
|
|
28
|
+
return;
|
|
29
|
+
isRegistered = true;
|
|
30
|
+
registerWithDevSettings(onToggle);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Update the toggle callback (when component re-renders)
|
|
34
|
+
*/
|
|
35
|
+
function updateDevMenuCallback(onToggle) {
|
|
36
|
+
toggleCallback = onToggle;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Register with React Native's DevSettings
|
|
40
|
+
*/
|
|
41
|
+
function registerWithDevSettings(onToggle) {
|
|
42
|
+
try {
|
|
43
|
+
if (react_native_1.DevSettings && typeof react_native_1.DevSettings.addMenuItem === 'function') {
|
|
44
|
+
react_native_1.DevSettings.addMenuItem('Toggle Dev Inspector', () => {
|
|
45
|
+
toggleCallback?.();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// DevSettings not available (might be production build)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if dev menu is available
|
|
55
|
+
*/
|
|
56
|
+
function isDevMenuAvailable() {
|
|
57
|
+
if (typeof __DEV__ === 'undefined' || !__DEV__)
|
|
58
|
+
return false;
|
|
59
|
+
try {
|
|
60
|
+
if (react_native_1.DevSettings && typeof react_native_1.DevSettings.addMenuItem === 'function') {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// ignore
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Instructions for opening dev menu on different platforms
|
|
71
|
+
*/
|
|
72
|
+
function getDevMenuInstructions() {
|
|
73
|
+
if (react_native_1.Platform.OS === 'ios') {
|
|
74
|
+
return 'Shake device or press Cmd+D to open dev menu, then tap "Toggle Dev Inspector"';
|
|
75
|
+
}
|
|
76
|
+
else if (react_native_1.Platform.OS === 'android') {
|
|
77
|
+
return 'Shake device or press Cmd+M to open dev menu, then tap "Toggle Dev Inspector"';
|
|
78
|
+
}
|
|
79
|
+
return 'Shake device to open dev menu, then tap "Toggle Dev Inspector"';
|
|
80
|
+
}
|
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editor launching utilities
|
|
3
|
+
* Only Cursor is supported.
|
|
4
|
+
*/
|
|
5
|
+
import type { SourceLocation } from './types';
|
|
6
|
+
export interface LaunchEditorOptions {
|
|
7
|
+
/** Source code information */
|
|
8
|
+
source: SourceLocation;
|
|
9
|
+
/** Editor name - only 'cursor' is supported */
|
|
10
|
+
editor?: string;
|
|
11
|
+
/** Dev server URL (for Metro-based launching) */
|
|
12
|
+
devServerUrl?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Main function to launch Cursor editor
|
|
16
|
+
* Tries multiple methods:
|
|
17
|
+
* 1. URL scheme (deep linking)
|
|
18
|
+
* 2. Metro inspector endpoint
|
|
19
|
+
*/
|
|
20
|
+
export declare function launchEditor(options: LaunchEditorOptions): Promise<boolean>;
|
package/dist/editor.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Editor launching utilities
|
|
4
|
+
* Only Cursor is supported.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.launchEditor = launchEditor;
|
|
8
|
+
const react_native_1 = require("react-native");
|
|
9
|
+
/**
|
|
10
|
+
* Default dev server URL based on platform
|
|
11
|
+
*/
|
|
12
|
+
function getDefaultDevServerUrl() {
|
|
13
|
+
if (react_native_1.Platform.OS === 'android') {
|
|
14
|
+
return 'http://10.0.2.2:8081';
|
|
15
|
+
}
|
|
16
|
+
return 'http://localhost:8081';
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Build query string for editor endpoint
|
|
20
|
+
*/
|
|
21
|
+
function buildEditorQueryString(source) {
|
|
22
|
+
const params = new URLSearchParams();
|
|
23
|
+
params.set('file', source.file);
|
|
24
|
+
if (source.line) {
|
|
25
|
+
params.set('line', String(source.line));
|
|
26
|
+
}
|
|
27
|
+
if (source.column) {
|
|
28
|
+
params.set('column', String(source.column));
|
|
29
|
+
}
|
|
30
|
+
params.set('editor', 'cursor');
|
|
31
|
+
return params.toString();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Launch editor via standard inspector endpoint
|
|
35
|
+
*/
|
|
36
|
+
async function launchEditorViaInspector(options) {
|
|
37
|
+
const { source, devServerUrl } = options;
|
|
38
|
+
const baseUrl = devServerUrl || getDefaultDevServerUrl();
|
|
39
|
+
const queryString = buildEditorQueryString(source);
|
|
40
|
+
const url = `${baseUrl}/__inspect-open-in-editor?${queryString}`;
|
|
41
|
+
try {
|
|
42
|
+
const response = await fetch(url, { method: 'GET' });
|
|
43
|
+
return response.ok;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Try to launch Cursor via URL scheme (deep linking)
|
|
51
|
+
*/
|
|
52
|
+
async function launchEditorViaUrlScheme(source) {
|
|
53
|
+
const { file, line, column } = source;
|
|
54
|
+
const url = `cursor://file${file}:${line}:${column || 1}`;
|
|
55
|
+
try {
|
|
56
|
+
const canOpen = await react_native_1.Linking.canOpenURL(url);
|
|
57
|
+
if (canOpen) {
|
|
58
|
+
await react_native_1.Linking.openURL(url);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Main function to launch Cursor editor
|
|
69
|
+
* Tries multiple methods:
|
|
70
|
+
* 1. URL scheme (deep linking)
|
|
71
|
+
* 2. Metro inspector endpoint
|
|
72
|
+
*/
|
|
73
|
+
async function launchEditor(options) {
|
|
74
|
+
const { source } = options;
|
|
75
|
+
console.log('\n🚀 [rn-ave] launchEditor called');
|
|
76
|
+
console.log(' source:', source);
|
|
77
|
+
// Try URL scheme first
|
|
78
|
+
console.log(' Trying URL scheme...');
|
|
79
|
+
const urlSuccess = await launchEditorViaUrlScheme(source);
|
|
80
|
+
console.log(' URL scheme result:', urlSuccess);
|
|
81
|
+
if (urlSuccess) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
// Try Metro inspector endpoint
|
|
85
|
+
console.log(' Trying Metro inspector endpoint...');
|
|
86
|
+
const inspectorSuccess = await launchEditorViaInspector(options);
|
|
87
|
+
console.log(' Inspector endpoint result:', inspectorSuccess);
|
|
88
|
+
if (inspectorSuccess) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
console.log(' All methods failed');
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FiberRoot, RNDevToolsHook } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Installs the DevTools hook to capture React fiber tree
|
|
4
|
+
* Must be called BEFORE React Native initializes
|
|
5
|
+
*/
|
|
6
|
+
export declare function installHook(): RNDevToolsHook;
|
|
7
|
+
/**
|
|
8
|
+
* Gets the current fiber root (usually there's only one in RN)
|
|
9
|
+
*/
|
|
10
|
+
export declare function getFiberRoot(): FiberRoot | null;
|
|
11
|
+
/**
|
|
12
|
+
* Debug function to log hook state
|
|
13
|
+
*/
|
|
14
|
+
export declare function debugHookState(): void;
|
|
15
|
+
/**
|
|
16
|
+
* Checks if the hook has been installed
|
|
17
|
+
*/
|
|
18
|
+
export declare function isHookInstalled(): boolean;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.installHook = installHook;
|
|
4
|
+
exports.getFiberRoot = getFiberRoot;
|
|
5
|
+
exports.debugHookState = debugHookState;
|
|
6
|
+
exports.isHookInstalled = isHookInstalled;
|
|
7
|
+
// Storage for fiber roots
|
|
8
|
+
const fiberRoots = new Map();
|
|
9
|
+
let hookInstalled = false;
|
|
10
|
+
/**
|
|
11
|
+
* Wraps an existing DevTools hook to capture fiber roots
|
|
12
|
+
*/
|
|
13
|
+
function wrapExistingHook(existingHook) {
|
|
14
|
+
const originalOnCommit = existingHook.onCommitFiberRoot;
|
|
15
|
+
existingHook.onCommitFiberRoot = function (rendererID, root) {
|
|
16
|
+
fiberRoots.set(rendererID, root);
|
|
17
|
+
if (originalOnCommit) {
|
|
18
|
+
originalOnCommit.call(this, rendererID, root);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
return existingHook;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Installs the DevTools hook to capture React fiber tree
|
|
25
|
+
* Must be called BEFORE React Native initializes
|
|
26
|
+
*/
|
|
27
|
+
function installHook() {
|
|
28
|
+
if (hookInstalled) {
|
|
29
|
+
return globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
30
|
+
}
|
|
31
|
+
// Check if hook already exists
|
|
32
|
+
if (globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
|
|
33
|
+
hookInstalled = true;
|
|
34
|
+
return wrapExistingHook(globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__);
|
|
35
|
+
}
|
|
36
|
+
// Create our own hook
|
|
37
|
+
const hook = {
|
|
38
|
+
renderers: new Map(),
|
|
39
|
+
inject(renderer) {
|
|
40
|
+
const id = this.renderers.size + 1;
|
|
41
|
+
this.renderers.set(id, renderer);
|
|
42
|
+
return id;
|
|
43
|
+
},
|
|
44
|
+
onCommitFiberRoot(rendererID, root) {
|
|
45
|
+
fiberRoots.set(rendererID, root);
|
|
46
|
+
},
|
|
47
|
+
onCommitFiberUnmount(_rendererID, _fiber) {
|
|
48
|
+
// Cleanup references if needed
|
|
49
|
+
},
|
|
50
|
+
getFiberRoots(rendererID) {
|
|
51
|
+
const root = fiberRoots.get(rendererID);
|
|
52
|
+
return root ? new Set([root]) : new Set();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook;
|
|
56
|
+
hookInstalled = true;
|
|
57
|
+
return hook;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Gets the current fiber root (usually there's only one in RN)
|
|
61
|
+
*/
|
|
62
|
+
function getFiberRoot() {
|
|
63
|
+
// Try to get from stored roots
|
|
64
|
+
for (const root of fiberRoots.values()) {
|
|
65
|
+
if (root && root.current) {
|
|
66
|
+
return root;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Try to get from DevTools hook
|
|
70
|
+
const hook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
71
|
+
if (hook?.getFiberRoots) {
|
|
72
|
+
for (const rendererID of hook.renderers.keys()) {
|
|
73
|
+
const roots = hook.getFiberRoots(rendererID);
|
|
74
|
+
for (const root of roots) {
|
|
75
|
+
if (root && root.current) {
|
|
76
|
+
return root;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Last resort: try to find fiber from any stored root
|
|
82
|
+
if (hook?.renderers) {
|
|
83
|
+
for (const [id] of hook.renderers) {
|
|
84
|
+
const roots = fiberRoots.get(id);
|
|
85
|
+
if (roots && roots.current) {
|
|
86
|
+
return roots;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Debug function to log hook state
|
|
94
|
+
*/
|
|
95
|
+
function debugHookState() {
|
|
96
|
+
// Debug logging disabled
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Checks if the hook has been installed
|
|
100
|
+
*/
|
|
101
|
+
function isHookInstalled() {
|
|
102
|
+
return hookInstalled;
|
|
103
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Fiber, SourceLocation } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts source location from a fiber node (non-recursive)
|
|
4
|
+
*/
|
|
5
|
+
export declare function getSourceLocation(fiber: Fiber): SourceLocation | null;
|
|
6
|
+
/**
|
|
7
|
+
* Recursive version of getSourceLocation that follows _debugOwner
|
|
8
|
+
*/
|
|
9
|
+
export declare function getSourceLocationRecursive(fiber: Fiber): SourceLocation | null;
|
|
10
|
+
/**
|
|
11
|
+
* Checks if a fiber's source location is from node_modules
|
|
12
|
+
*/
|
|
13
|
+
export declare function isFromNodeModules(fiber: Fiber): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Formats source location as a readable string
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatSourceLocation(source: SourceLocation | null): string;
|
|
18
|
+
/**
|
|
19
|
+
* Gets relative path from absolute path (simple version)
|
|
20
|
+
*/
|
|
21
|
+
export declare function getRelativePath(absolutePath: string, rootDir?: string): string;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSourceLocation = getSourceLocation;
|
|
4
|
+
exports.getSourceLocationRecursive = getSourceLocationRecursive;
|
|
5
|
+
exports.isFromNodeModules = isFromNodeModules;
|
|
6
|
+
exports.formatSourceLocation = formatSourceLocation;
|
|
7
|
+
exports.getRelativePath = getRelativePath;
|
|
8
|
+
/**
|
|
9
|
+
* Extracts source location from a fiber node (non-recursive)
|
|
10
|
+
*/
|
|
11
|
+
function getSourceLocation(fiber) {
|
|
12
|
+
// Strategy 1: Try custom prop from our Babel plugin (PRIMARY)
|
|
13
|
+
const rnAveMeta = fiber.memoizedProps?.__rnAve;
|
|
14
|
+
if (rnAveMeta && rnAveMeta.file) {
|
|
15
|
+
console.log(' [source] Found via __rnAve prop:', rnAveMeta.file);
|
|
16
|
+
return {
|
|
17
|
+
file: rnAveMeta.file,
|
|
18
|
+
line: rnAveMeta.line,
|
|
19
|
+
column: rnAveMeta.column,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
// Strategy 2: Try __rnInspect (legacy or standard RN metadata - FALLBACK)
|
|
23
|
+
const rnInspect = fiber.memoizedProps?.__rnInspect;
|
|
24
|
+
if (rnInspect) {
|
|
25
|
+
if (rnInspect.fileName) {
|
|
26
|
+
console.log(' [source] Found via __rnInspect (fileName):', rnInspect.fileName);
|
|
27
|
+
return {
|
|
28
|
+
file: rnInspect.fileName,
|
|
29
|
+
line: rnInspect.lineNumber,
|
|
30
|
+
column: rnInspect.columnNumber,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (rnInspect.file) {
|
|
34
|
+
console.log(' [source] Found via __rnInspect (file):', rnInspect.file);
|
|
35
|
+
return {
|
|
36
|
+
file: rnInspect.file,
|
|
37
|
+
line: rnInspect.line,
|
|
38
|
+
column: rnInspect.column,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Strategy 3: Try _debugSource (React development mode)
|
|
43
|
+
if (fiber._debugSource) {
|
|
44
|
+
console.log(' [source] Found via _debugSource:', fiber._debugSource.fileName);
|
|
45
|
+
return {
|
|
46
|
+
file: fiber._debugSource.fileName,
|
|
47
|
+
line: fiber._debugSource.lineNumber,
|
|
48
|
+
column: fiber._debugSource.columnNumber,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Recursive version of getSourceLocation that follows _debugOwner
|
|
55
|
+
*/
|
|
56
|
+
function getSourceLocationRecursive(fiber) {
|
|
57
|
+
const localSource = getSourceLocation(fiber);
|
|
58
|
+
if (localSource)
|
|
59
|
+
return localSource;
|
|
60
|
+
if (fiber._debugOwner) {
|
|
61
|
+
return getSourceLocationRecursive(fiber._debugOwner);
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Checks if a fiber's source location is from node_modules
|
|
67
|
+
*/
|
|
68
|
+
function isFromNodeModules(fiber) {
|
|
69
|
+
const source = getSourceLocation(fiber);
|
|
70
|
+
if (!source?.file)
|
|
71
|
+
return false;
|
|
72
|
+
return source.file.includes('node_modules');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Formats source location as a readable string
|
|
76
|
+
*/
|
|
77
|
+
function formatSourceLocation(source) {
|
|
78
|
+
if (!source)
|
|
79
|
+
return 'Unknown location';
|
|
80
|
+
const column = source.column ? `:${source.column}` : '';
|
|
81
|
+
return `${source.file}:${source.line}${column}`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Gets relative path from absolute path (simple version)
|
|
85
|
+
*/
|
|
86
|
+
function getRelativePath(absolutePath, rootDir) {
|
|
87
|
+
if (!rootDir)
|
|
88
|
+
return absolutePath;
|
|
89
|
+
// Simple relative path calculation
|
|
90
|
+
if (absolutePath.startsWith(rootDir)) {
|
|
91
|
+
return absolutePath.slice(rootDir.length + 1);
|
|
92
|
+
}
|
|
93
|
+
return absolutePath;
|
|
94
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Fiber, FiberRoot, ComponentInfo } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Finds a fiber node by its native tag
|
|
4
|
+
*/
|
|
5
|
+
export declare function findFiberByNativeTag(nativeTag: number, fiberRoot: FiberRoot): Fiber | null;
|
|
6
|
+
/**
|
|
7
|
+
* Gets the display name of a component from its fiber
|
|
8
|
+
*/
|
|
9
|
+
export declare function getDisplayName(fiber: Fiber): string;
|
|
10
|
+
/**
|
|
11
|
+
* Gets the component hierarchy from a fiber node up to the root
|
|
12
|
+
*/
|
|
13
|
+
export declare function getComponentHierarchy(fiber: Fiber): ComponentInfo[];
|
|
14
|
+
/**
|
|
15
|
+
* Gets all props from a fiber, excluding internal ones
|
|
16
|
+
*/
|
|
17
|
+
export declare function getCleanProps(fiber: Fiber): Record<string, any>;
|
|
18
|
+
/**
|
|
19
|
+
* Finds the nearest composite component ancestor
|
|
20
|
+
* @param fiber - The starting fiber node
|
|
21
|
+
* @param skipNodeModules - If true, skips components from node_modules and returns the nearest user-code component
|
|
22
|
+
*/
|
|
23
|
+
export declare function findNearestComposite(fiber: Fiber, skipNodeModules?: boolean): Fiber | null;
|
|
24
|
+
/**
|
|
25
|
+
* Collects all host component fibers (View, Text, etc.) from the tree
|
|
26
|
+
*/
|
|
27
|
+
export declare function collectAllHostFibers(fiberRoot: FiberRoot): Fiber[];
|