react-doctor-cli-dev 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.
Files changed (82) hide show
  1. package/backend/.env +3 -0
  2. package/backend/dist/index.js +43 -0
  3. package/backend/dist/middleware/auth.js +16 -0
  4. package/backend/dist/routes/reports.js +93 -0
  5. package/backend/package-lock.json +2000 -0
  6. package/backend/package.json +30 -0
  7. package/backend/src/db.ts +24 -0
  8. package/backend/src/index.ts +49 -0
  9. package/backend/src/middleware/auth.ts +21 -0
  10. package/backend/src/routes/reports.ts +110 -0
  11. package/backend/tsconfig.json +12 -0
  12. package/cli/bin/react-doctor.js +29 -0
  13. package/cli/dist/commands/analyze.js +125 -0
  14. package/cli/dist/commands/full.js +366 -0
  15. package/cli/dist/commands/install.js +138 -0
  16. package/cli/dist/commands/profile.js +166 -0
  17. package/cli/dist/index.js +78 -0
  18. package/cli/dist/ui.js +113 -0
  19. package/cli/package-lock.json +936 -0
  20. package/cli/package.json +34 -0
  21. package/cli/src/commands/analyze.ts +162 -0
  22. package/cli/src/commands/full.ts +574 -0
  23. package/cli/src/commands/install.ts +163 -0
  24. package/cli/src/commands/profile.ts +246 -0
  25. package/cli/src/index.ts +84 -0
  26. package/cli/src/ui.ts +120 -0
  27. package/cli/tsconfig.json +16 -0
  28. package/core/report-compiler/index.ts +359 -0
  29. package/core/report-compiler/test-report-compiler.ts +126 -0
  30. package/core/rule-engine/context-builder.ts +146 -0
  31. package/core/rule-engine/evaluator.ts +131 -0
  32. package/core/rule-engine/index.ts +222 -0
  33. package/core/rule-engine/rules.json +304 -0
  34. package/core/rule-engine/suggestion-builder.ts +209 -0
  35. package/core/rule-engine/test-rule-engine.ts +144 -0
  36. package/core/rule-engine/types.ts +202 -0
  37. package/core/runtime/profiler/browser.ts +121 -0
  38. package/core/runtime/profiler/collectors.ts +216 -0
  39. package/core/runtime/profiler/index.ts +311 -0
  40. package/core/runtime/profiler/porfiler.ts +967 -0
  41. package/core/runtime/profiler/route-scanner.ts +76 -0
  42. package/core/runtime/profiler/score.ts +59 -0
  43. package/core/runtime/profiler/server.ts +115 -0
  44. package/core/runtime/profiler/types.ts +65 -0
  45. package/core/runtime/test-runtime-profiler.ts +226 -0
  46. package/core/static-ana/static/analyzer.ts +145 -0
  47. package/core/static-ana/static/ast-parser.ts +31 -0
  48. package/core/static-ana/static/detectors/console-log.ts +49 -0
  49. package/core/static-ana/static/detectors/dead-code.ts +51 -0
  50. package/core/static-ana/static/detectors/effect-loop.ts +45 -0
  51. package/core/static-ana/static/detectors/index.ts +16 -0
  52. package/core/static-ana/static/detectors/inline-function.ts +59 -0
  53. package/core/static-ana/static/detectors/inline-style.ts +52 -0
  54. package/core/static-ana/static/detectors/large-component.ts +79 -0
  55. package/core/static-ana/static/detectors/missing-key.ts +56 -0
  56. package/core/static-ana/static/detectors/missing-memo.ts +59 -0
  57. package/core/static-ana/static/detectors/prop-drilling.ts +66 -0
  58. package/core/static-ana/static/helpers.ts +81 -0
  59. package/core/static-ana/static/scanner.ts +93 -0
  60. package/core/static-ana/test-analyzer.ts +115 -0
  61. package/core/static-ana/types.ts +25 -0
  62. package/core/tests/mock-react-project/src/app.tsx +22 -0
  63. package/core/tests/mock-react-project/src/components/Button.tsx +9 -0
  64. package/core/tests/mock-react-project/src/components/Header.tsx +3 -0
  65. package/core/tests/mock-react-project/src/components/ListTesting.tsx +51 -0
  66. package/core/tests/mock-react-project/src/components/UserDashboard.tsx +66 -0
  67. package/core/tests/mock-react-project/src/utils.ts +4 -0
  68. package/package.json +55 -0
  69. package/react-doctor-cli-dev-1.0.0.tgz +0 -0
  70. package/shared/dist/index.d.ts +2 -0
  71. package/shared/dist/index.js +19 -0
  72. package/shared/dist/schemas.d.ts +91 -0
  73. package/shared/dist/schemas.js +82 -0
  74. package/shared/dist/types.d.ts +44 -0
  75. package/shared/dist/types.js +2 -0
  76. package/shared/package-lock.json +47 -0
  77. package/shared/package.json +21 -0
  78. package/shared/src/index.ts +4 -0
  79. package/shared/src/schemas.ts +136 -0
  80. package/shared/src/types.ts +137 -0
  81. package/shared/tsconfig.json +15 -0
  82. package/tsconfig.json +25 -0
package/backend/.env ADDED
@@ -0,0 +1,3 @@
1
+ PORT=3000
2
+ API_KEY=react-doctor-secret-key-change-this
3
+ DB_PATH=./data/reports.db
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const express_1 = __importDefault(require("express"));
7
+ const cors_1 = __importDefault(require("cors"));
8
+ const helmet_1 = __importDefault(require("helmet"));
9
+ const dotenv_1 = __importDefault(require("dotenv"));
10
+ const reports_1 = __importDefault(require("./routes/reports"));
11
+ dotenv_1.default.config();
12
+ // Debug: Check if API_KEY is loaded
13
+ console.log(`[Debug] API_KEY loaded: ${process.env.API_KEY ? '✓' : '✗'}`);
14
+ console.log(`[Debug] API_KEY value: ${process.env.API_KEY || 'NOT SET'}`);
15
+ const app = (0, express_1.default)();
16
+ const PORT = process.env.PORT || 3000;
17
+ // ─── SECURITY AND PARSING MIDDLEWARE ──────────────────────────────────────────
18
+ app.use((0, helmet_1.default)()); // adds security headers
19
+ app.use((0, cors_1.default)()); // allows dashboard to call the API
20
+ app.use(express_1.default.json({ limit: '50mb' })); // reports can be large (screenshots)
21
+ // ─── ROUTES ───────────────────────────────────────────────────────────────────
22
+ // Use only ONE path (plural is REST convention)
23
+ app.use('/api/reports', reports_1.default);
24
+ // ─── HEALTH CHECK - NO AUTH, USED TO VERIFY SERVER IS UP ──────────────────────
25
+ app.get('/health', (_req, res) => {
26
+ res.json({
27
+ status: 'ok',
28
+ timestamp: new Date().toISOString()
29
+ });
30
+ });
31
+ // ─── 404 HANDLER ──────────────────────────────────────────────────────────────
32
+ app.use((req, res) => {
33
+ res.status(404).json({ message: 'Route not found' });
34
+ });
35
+ // ─── GLOBAL ERROR HANDLER ─────────────────────────────────────────────────────
36
+ app.use((err, _req, res, _next) => {
37
+ console.error(err.stack);
38
+ res.status(500).json({ message: 'Internal Server Error' });
39
+ });
40
+ // ─── START THE SERVER ─────────────────────────────────────────────────────────
41
+ app.listen(PORT, () => {
42
+ console.log(`React Doctor backend running on http://localhost:${PORT}`);
43
+ });
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireApiKey = requireApiKey;
4
+ function requireApiKey(req, res, next) {
5
+ const keyHeader = req.headers["x-api-key"];
6
+ const key = Array.isArray(keyHeader) ? keyHeader[0] : keyHeader;
7
+ const expectedKey = process.env.API_KEY?.trim();
8
+ // Debug log
9
+ console.log(`[Auth] Received: "${key}", Expected: "${expectedKey}"`);
10
+ if (!key || key.trim() !== expectedKey) {
11
+ console.warn(`[Auth] API key mismatch!`);
12
+ res.status(401).json({ error: "Unauthorized — invalid or missing API key" });
13
+ return;
14
+ }
15
+ next();
16
+ }
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const express_1 = require("express");
7
+ const db_1 = __importDefault(require("../db"));
8
+ const auth_1 = require("../middleware/auth");
9
+ const router = (0, express_1.Router)();
10
+ router.get("/", (req, res) => {
11
+ try {
12
+ const rows = db_1.default.prepare(`
13
+ SELECT id, project, score, grade, analyzed_at, created_at
14
+ FROM reports
15
+ ORDER BY created_at DESC
16
+ LIMIT 50
17
+ `).all();
18
+ res.json({ count: rows.length, reports: rows });
19
+ }
20
+ catch (err) {
21
+ res.status(500).json({ error: "Internal server error" });
22
+ }
23
+ });
24
+ router.get("/project/:name", (req, res) => {
25
+ try {
26
+ const rows = db_1.default.prepare(`
27
+ SELECT id, project, score, grade, analyzed_at, created_at
28
+ FROM reports
29
+ WHERE project = ?
30
+ ORDER BY created_at DESC
31
+ `).all(req.params.name);
32
+ res.json({
33
+ project: req.params.name,
34
+ count: rows.length,
35
+ reports: rows,
36
+ });
37
+ }
38
+ catch (err) {
39
+ res.status(500).json({ error: "Internal server error" });
40
+ }
41
+ });
42
+ // ==========================================
43
+ // Endpoint 1: POST /api/report/upload
44
+ // يستقبل التقرير من الـ CLI ويتحقق منه ثم يحفظه
45
+ // ==========================================
46
+ router.post("/upload", auth_1.requireApiKey, (req, res) => {
47
+ try {
48
+ const report = req.body;
49
+ // التحقق من وجود الحقول الإلزامية الثلاثة
50
+ if (!report || !report.projectName || !report.analyzedAt || report.performanceScore === undefined) {
51
+ res.status(400).json({ error: "Invalid report — missing required fields" });
52
+ return;
53
+ }
54
+ const grade = report.static?.grade ?? "N/A";
55
+ // تجهيز استعلام الإدخال لـ SQLite
56
+ const stmt = db_1.default.prepare(`
57
+ INSERT INTO reports (project, score, grade, analyzed_at, payload)
58
+ VALUES (?, ?, ?, ?, ?)
59
+ `);
60
+ // تنفيذ الاستعلام وحفظ جسم التقرير كـ string
61
+ const result = stmt.run(report.projectName, report.performanceScore, grade, report.analyzedAt, JSON.stringify(report));
62
+ res.status(201).json({
63
+ message: "Report saved successfully",
64
+ id: result.lastInsertRowid,
65
+ });
66
+ }
67
+ catch (err) {
68
+ console.error("Upload error:", err.message);
69
+ res.status(500).json({ error: "Internal server error" });
70
+ }
71
+ });
72
+ router.get("/:id", (req, res) => {
73
+ try {
74
+ const row = db_1.default.prepare("SELECT * FROM reports WHERE id = ?").get(req.params.id);
75
+ if (!row) {
76
+ res.status(404).json({ error: "Report not found" });
77
+ return;
78
+ }
79
+ res.json({
80
+ id: row.id,
81
+ project: row.project,
82
+ score: row.score,
83
+ grade: row.grade,
84
+ analyzedAt: row.analyzed_at,
85
+ createdAt: row.created_at,
86
+ report: JSON.parse(row.payload),
87
+ });
88
+ }
89
+ catch (err) {
90
+ res.status(500).json({ error: "Internal server error" });
91
+ }
92
+ });
93
+ exports.default = router;