@nhonh/react-debugger 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/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # ⚛️ React Debugger
2
+
3
+ Advanced debugging & performance optimization tool for ReactJS applications.
4
+
5
+ ## Quick Install
6
+
7
+ ```bash
8
+ npx react-debugger
9
+ ```
10
+
11
+ This will download the Chrome extension to your local machine.
12
+
13
+ ## Usage
14
+
15
+ ### Interactive Mode
16
+
17
+ ```bash
18
+ npx react-debugger
19
+ ```
20
+
21
+ Follow the prompts to choose installation directory.
22
+
23
+ ### Direct Install
24
+
25
+ ```bash
26
+ npx react-debugger ./my-extension
27
+ ```
28
+
29
+ ### Options
30
+
31
+ ```
32
+ -v, --version Show version number
33
+ -h, --help Show help
34
+ ```
35
+
36
+ ## Loading the Extension in Chrome
37
+
38
+ After installation:
39
+
40
+ 1. Open `chrome://extensions/` in Chrome
41
+ 2. Enable **Developer mode** (toggle in top right)
42
+ 3. Click **Load unpacked**
43
+ 4. Select the folder where you installed the extension
44
+
45
+ ## Features
46
+
47
+ - 🎯 **UI & State Issues** - Detect direct state mutation, missing keys, index as key
48
+ - ⚡ **Performance Analysis** - Track re-renders, identify excessive renders
49
+ - 🔄 **Side Effects** - Find missing cleanup, dependency issues in useEffect
50
+ - 📐 **CLS Monitor** - Track Cumulative Layout Shift in real-time
51
+ - 🗄️ **Redux DevTools** - View state tree, dispatch actions manually
52
+ - 📊 **Timeline** - Visual timeline of all React events
53
+ - 💾 **Memory** - Monitor memory usage and detect leaks
54
+
55
+ ## Requirements
56
+
57
+ - Node.js >= 18.0.0
58
+ - Chrome, Brave, or any Chromium-based browser
59
+
60
+ ## Links
61
+
62
+ - [GitHub Repository](https://github.com/nhonh/react-debugger-extension)
63
+ - [Report Issues](https://github.com/nhonh/react-debugger-extension/issues)
64
+
65
+ ## License
66
+
67
+ MIT © NhoNH
package/bin/cli.js ADDED
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { intro, outro, text, spinner, confirm, isCancel } from '@clack/prompts';
4
+ import pc from 'picocolors';
5
+ import { downloadAndExtract } from '../src/install.js';
6
+ import path from 'node:path';
7
+ import fs from 'node:fs';
8
+
9
+ const VERSION = '1.0.0';
10
+ const EXTENSION_NAME = 'React Debugger';
11
+
12
+ async function main() {
13
+ const args = process.argv.slice(2);
14
+
15
+ if (args.includes('--version') || args.includes('-v')) {
16
+ console.log(`${EXTENSION_NAME} v${VERSION}`);
17
+ process.exit(0);
18
+ }
19
+
20
+ if (args.includes('--help') || args.includes('-h')) {
21
+ console.log(`
22
+ ${pc.cyan(EXTENSION_NAME)} - Chrome Extension Installer
23
+
24
+ ${pc.yellow('Usage:')}
25
+ npx react-debugger [destination]
26
+
27
+ ${pc.yellow('Options:')}
28
+ -v, --version Show version number
29
+ -h, --help Show help
30
+
31
+ ${pc.yellow('Examples:')}
32
+ npx react-debugger # Interactive mode
33
+ npx react-debugger ./my-extension # Direct install to folder
34
+ `);
35
+ process.exit(0);
36
+ }
37
+
38
+ console.log();
39
+ intro(pc.bgCyan(pc.black(` ${EXTENSION_NAME} Extension Installer `)));
40
+
41
+ let destination = args[0];
42
+
43
+ if (!destination) {
44
+ const destInput = await text({
45
+ message: 'Where should we install the extension?',
46
+ placeholder: './react-debugger',
47
+ initialValue: './react-debugger',
48
+ validate: (value) => {
49
+ if (!value || value.trim() === '') {
50
+ return 'Please enter a destination path';
51
+ }
52
+ },
53
+ });
54
+
55
+ if (isCancel(destInput)) {
56
+ outro(pc.yellow('Installation cancelled.'));
57
+ process.exit(0);
58
+ }
59
+
60
+ destination = destInput;
61
+ }
62
+
63
+ const fullPath = path.resolve(destination);
64
+
65
+ if (fs.existsSync(fullPath)) {
66
+ const files = fs.readdirSync(fullPath);
67
+ if (files.length > 0) {
68
+ const shouldOverwrite = await confirm({
69
+ message: `Directory ${pc.yellow(fullPath)} is not empty. Overwrite?`,
70
+ initialValue: false,
71
+ });
72
+
73
+ if (isCancel(shouldOverwrite) || !shouldOverwrite) {
74
+ outro(pc.yellow('Installation cancelled.'));
75
+ process.exit(0);
76
+ }
77
+ }
78
+ }
79
+
80
+ const s = spinner();
81
+ s.start('Downloading React Debugger extension...');
82
+
83
+ try {
84
+ await downloadAndExtract(fullPath);
85
+ s.stop(pc.green('Download complete!'));
86
+
87
+ console.log();
88
+ console.log(pc.dim('─'.repeat(50)));
89
+ console.log();
90
+ console.log(pc.bold('Next steps to load the extension in Chrome:'));
91
+ console.log();
92
+ console.log(` ${pc.cyan('1.')} Open ${pc.yellow('chrome://extensions/')} in Chrome`);
93
+ console.log(` ${pc.cyan('2.')} Enable ${pc.yellow('Developer mode')} (toggle in top right)`);
94
+ console.log(` ${pc.cyan('3.')} Click ${pc.yellow('Load unpacked')}`);
95
+ console.log(` ${pc.cyan('4.')} Select the folder:`);
96
+ console.log(` ${pc.green(fullPath)}`);
97
+ console.log();
98
+ console.log(pc.dim('─'.repeat(50)));
99
+ console.log();
100
+
101
+ outro(pc.green('✓ Installation successful!'));
102
+ } catch (err) {
103
+ s.stop(pc.red('Download failed!'));
104
+ console.error();
105
+ console.error(pc.red('Error:'), err.message);
106
+ console.error();
107
+ console.error(pc.dim('If this persists, please report at:'));
108
+ console.error(pc.dim('https://github.com/nhonh/react-debugger-extension/issues'));
109
+ process.exit(1);
110
+ }
111
+ }
112
+
113
+ main().catch((err) => {
114
+ console.error(pc.red('Unexpected error:'), err);
115
+ process.exit(1);
116
+ });
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@nhonh/react-debugger",
3
+ "version": "1.0.0",
4
+ "description": "Advanced debugging & performance optimization tool for ReactJS applications - Chrome Extension",
5
+ "author": "NhoNH",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "bin": {
9
+ "react-debugger": "bin/cli.js"
10
+ },
11
+ "files": [
12
+ "bin/",
13
+ "src/"
14
+ ],
15
+ "keywords": [
16
+ "react",
17
+ "debugger",
18
+ "devtools",
19
+ "chrome-extension",
20
+ "performance",
21
+ "redux",
22
+ "profiler",
23
+ "developer-tools"
24
+ ],
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/nhonh/react-debugger-extension.git"
28
+ },
29
+ "homepage": "https://github.com/nhonh/react-debugger-extension#readme",
30
+ "bugs": {
31
+ "url": "https://github.com/nhonh/react-debugger-extension/issues"
32
+ },
33
+ "engines": {
34
+ "node": ">=18.0.0"
35
+ },
36
+ "dependencies": {
37
+ "@clack/prompts": "^0.9.1",
38
+ "picocolors": "^1.1.1",
39
+ "decompress": "^4.2.1"
40
+ }
41
+ }
package/src/install.js ADDED
@@ -0,0 +1,94 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import decompress from 'decompress';
5
+
6
+ const GITHUB_REPO = 'nhonh/react-debugger-extension';
7
+ const RELEASE_TAG = 'latest';
8
+
9
+ async function getLatestReleaseUrl() {
10
+ const apiUrl = `https://api.github.com/repos/${GITHUB_REPO}/releases/${RELEASE_TAG}`;
11
+
12
+ const response = await fetch(apiUrl, {
13
+ headers: {
14
+ 'Accept': 'application/vnd.github.v3+json',
15
+ 'User-Agent': 'react-debugger-cli',
16
+ },
17
+ });
18
+
19
+ if (!response.ok) {
20
+ if (response.status === 404) {
21
+ return getFallbackUrl();
22
+ }
23
+ throw new Error(`Failed to fetch release info: ${response.statusText}`);
24
+ }
25
+
26
+ const release = await response.json();
27
+ const asset = release.assets?.find(a => a.name === 'react-debugger.zip');
28
+
29
+ if (asset) {
30
+ return asset.browser_download_url;
31
+ }
32
+
33
+ return getFallbackUrl();
34
+ }
35
+
36
+ function getFallbackUrl() {
37
+ return `https://github.com/${GITHUB_REPO}/releases/latest/download/react-debugger.zip`;
38
+ }
39
+
40
+ async function downloadFromUrl(url) {
41
+ const response = await fetch(url, {
42
+ headers: {
43
+ 'User-Agent': 'react-debugger-cli',
44
+ },
45
+ redirect: 'follow',
46
+ });
47
+
48
+ if (!response.ok) {
49
+ throw new Error(`Download failed: ${response.status} ${response.statusText}`);
50
+ }
51
+
52
+ const arrayBuffer = await response.arrayBuffer();
53
+ return Buffer.from(arrayBuffer);
54
+ }
55
+
56
+ export async function downloadAndExtract(dest) {
57
+ await fs.mkdir(dest, { recursive: true });
58
+
59
+ const existingFiles = await fs.readdir(dest);
60
+ for (const file of existingFiles) {
61
+ await fs.rm(path.join(dest, file), { recursive: true, force: true });
62
+ }
63
+
64
+ let downloadUrl;
65
+ try {
66
+ downloadUrl = await getLatestReleaseUrl();
67
+ } catch {
68
+ downloadUrl = getFallbackUrl();
69
+ }
70
+
71
+ const buffer = await downloadFromUrl(downloadUrl);
72
+
73
+ await decompress(buffer, dest, {
74
+ strip: 0,
75
+ });
76
+
77
+ const files = await fs.readdir(dest);
78
+ if (!files.includes('manifest.json')) {
79
+ const subDirs = files.filter(async (f) => {
80
+ const stat = await fs.stat(path.join(dest, f));
81
+ return stat.isDirectory();
82
+ });
83
+
84
+ if (subDirs.length === 1) {
85
+ const subDir = path.join(dest, subDirs[0]);
86
+ const subFiles = await fs.readdir(subDir);
87
+
88
+ for (const file of subFiles) {
89
+ await fs.rename(path.join(subDir, file), path.join(dest, file));
90
+ }
91
+ await fs.rmdir(subDir);
92
+ }
93
+ }
94
+ }