sickbay 1.15.2 → 1.15.3
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/dist/{DiffApp-ACTRBPEJ.js → DiffApp-M3D3HGI4.js} +2 -2
- package/dist/{DoctorApp-AT2VCFDQ.js → DoctorApp-VIDISA3A.js} +3 -3
- package/dist/{FixApp-OFGNY2UR.js → FixApp-HT7PHJKO.js} +3 -3
- package/dist/{StatsApp-YQJOEQIW.js → StatsApp-GOCP43YN.js} +3 -3
- package/dist/{TrendApp-IBHR4R5D.js → TrendApp-CB7CNPZI.js} +3 -3
- package/dist/{TuiApp-APJXORT5.js → TuiApp-SX22YRN7.js} +4 -4
- package/dist/{chunk-6GIJCWXK.js → chunk-BI2RMQIV.js} +3 -1
- package/dist/{chunk-J4C4MHXN.js → chunk-O23F4LLA.js} +1 -1
- package/dist/{chunk-QYJLQBEL.js → chunk-QAVKOJFG.js} +1 -1
- package/dist/config.js +1 -1
- package/dist/{dist-Q76NLAL5.js → dist-CEJKDCQM.js} +1 -1
- package/dist/index.js +67 -53
- package/dist/{init-XUMTXUVV.js → init-WGMAAQSO.js} +1 -1
- package/dist/{resolve-package-RN2JUNIX.js → resolve-package-FYX3J6PS.js} +2 -2
- package/dist/{web-U22VUQGS.js → web-KRYFOBSH.js} +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Header
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-O23F4LLA.js";
|
|
4
4
|
|
|
5
5
|
// src/components/DiffApp.tsx
|
|
6
6
|
import React, { useState, useEffect } from "react";
|
|
@@ -119,7 +119,7 @@ function DiffApp({ projectPath, branch, jsonOutput, checks, verbose }) {
|
|
|
119
119
|
useEffect(() => {
|
|
120
120
|
(async () => {
|
|
121
121
|
try {
|
|
122
|
-
const { runSickbay } = await import("./dist-
|
|
122
|
+
const { runSickbay } = await import("./dist-CEJKDCQM.js");
|
|
123
123
|
const currentReport = await runSickbay({
|
|
124
124
|
projectPath,
|
|
125
125
|
checks,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
shortName
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QAVKOJFG.js";
|
|
4
4
|
import {
|
|
5
5
|
Header
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-O23F4LLA.js";
|
|
7
7
|
import {
|
|
8
8
|
detectPackageManager,
|
|
9
9
|
detectProject
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-BI2RMQIV.js";
|
|
11
11
|
|
|
12
12
|
// src/components/DoctorApp.tsx
|
|
13
13
|
import React, { useState, useEffect } from "react";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
shortName
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QAVKOJFG.js";
|
|
4
4
|
import {
|
|
5
5
|
ProgressList
|
|
6
6
|
} from "./chunk-MBVA75EM.js";
|
|
7
7
|
import {
|
|
8
8
|
Header
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-O23F4LLA.js";
|
|
10
10
|
import {
|
|
11
11
|
runSickbay
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-BI2RMQIV.js";
|
|
13
13
|
|
|
14
14
|
// src/components/FixApp.tsx
|
|
15
15
|
import React, { useState, useEffect, useCallback } from "react";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
shortName
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QAVKOJFG.js";
|
|
4
4
|
import {
|
|
5
5
|
Header
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-O23F4LLA.js";
|
|
7
7
|
import {
|
|
8
8
|
detectProject
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-BI2RMQIV.js";
|
|
10
10
|
|
|
11
11
|
// src/components/StatsApp.tsx
|
|
12
12
|
import React, { useState, useEffect } from "react";
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
} from "./chunk-SHO3ZXTH.js";
|
|
5
5
|
import {
|
|
6
6
|
shortName
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QAVKOJFG.js";
|
|
8
8
|
import {
|
|
9
9
|
Header
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-O23F4LLA.js";
|
|
11
|
+
import "./chunk-BI2RMQIV.js";
|
|
12
12
|
import {
|
|
13
13
|
detectRegressions,
|
|
14
14
|
loadHistory
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
detectMonorepo,
|
|
15
15
|
runSickbay,
|
|
16
16
|
runSickbayMonorepo
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-BI2RMQIV.js";
|
|
18
18
|
import {
|
|
19
19
|
loadHistory
|
|
20
20
|
} from "./chunk-3OR2GFVE.js";
|
|
@@ -689,7 +689,7 @@ function TuiApp({
|
|
|
689
689
|
return () => timers.forEach(clearTimeout);
|
|
690
690
|
}, []);
|
|
691
691
|
useEffect7(() => {
|
|
692
|
-
checkForUpdate("1.15.
|
|
692
|
+
checkForUpdate("1.15.2").then((info) => {
|
|
693
693
|
if (info) setUpdateInfo(info);
|
|
694
694
|
});
|
|
695
695
|
}, []);
|
|
@@ -715,7 +715,7 @@ function TuiApp({
|
|
|
715
715
|
} catch {
|
|
716
716
|
}
|
|
717
717
|
try {
|
|
718
|
-
const { getDependencyTree } = await import("./dist-
|
|
718
|
+
const { getDependencyTree } = await import("./dist-CEJKDCQM.js");
|
|
719
719
|
const { saveDepTree } = await import("./history-XLNVZEDI.js");
|
|
720
720
|
const tree = await getDependencyTree(projectPath, result.projectInfo.packageManager);
|
|
721
721
|
saveDepTree(projectPath, tree);
|
|
@@ -819,7 +819,7 @@ function TuiApp({
|
|
|
819
819
|
const webReport = monorepoReportRef.current ?? reportRef.current;
|
|
820
820
|
if (!webReport) return;
|
|
821
821
|
try {
|
|
822
|
-
const { serveWeb } = await import("./web-
|
|
822
|
+
const { serveWeb } = await import("./web-KRYFOBSH.js");
|
|
823
823
|
const { default: openBrowser } = await import("open");
|
|
824
824
|
let aiService;
|
|
825
825
|
if (withAI && process.env.ANTHROPIC_API_KEY && !monorepoReportRef.current) {
|
|
@@ -361,7 +361,7 @@ var NextBestPracticesAdvisor = class extends BaseAdvisor {
|
|
|
361
361
|
const hasStrictMode = NEXT_CONFIG_FILES.some((f) => {
|
|
362
362
|
try {
|
|
363
363
|
const content = readFileSync2(join2(projectPath, f), "utf-8");
|
|
364
|
-
return
|
|
364
|
+
return /reactStrictMode\s*:\s*true/.test(content);
|
|
365
365
|
} catch {
|
|
366
366
|
return false;
|
|
367
367
|
}
|
|
@@ -581,6 +581,8 @@ function scanComponentFiles(dir) {
|
|
|
581
581
|
var LOCK_FILES = ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb"];
|
|
582
582
|
var UniversalBestPracticesAdvisor = class extends BaseAdvisor {
|
|
583
583
|
name = "universal-best-practices";
|
|
584
|
+
// Empty array means "applies to all frameworks" (see BaseAdvisor.isApplicableToContext).
|
|
585
|
+
// Explicit type annotation avoids the `never[]` widening that previously required a double cast.
|
|
584
586
|
frameworks = [];
|
|
585
587
|
async run(projectPath, _context) {
|
|
586
588
|
const recommendations = [];
|
|
@@ -11,7 +11,7 @@ var ASCII_ART = `
|
|
|
11
11
|
A vitals health check for your app
|
|
12
12
|
`.trim();
|
|
13
13
|
function Header({ projectName }) {
|
|
14
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "green" }, ASCII_ART), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " v", "1.15.
|
|
14
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "green" }, ASCII_ART), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " v", "1.15.2")), projectName && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " Analyzing "), /* @__PURE__ */ React.createElement(Text, { bold: true, color: "white" }, projectName)));
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export {
|
package/dist/config.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -8,40 +8,54 @@ import {
|
|
|
8
8
|
} from "./chunk-TYG7ZQBP.js";
|
|
9
9
|
import {
|
|
10
10
|
Header
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-O23F4LLA.js";
|
|
12
12
|
import {
|
|
13
13
|
getScoreEmoji,
|
|
14
14
|
runSickbay,
|
|
15
15
|
runSickbayMonorepo
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-BI2RMQIV.js";
|
|
17
17
|
|
|
18
18
|
// src/index.ts
|
|
19
19
|
import { existsSync } from "fs";
|
|
20
20
|
import { homedir } from "os";
|
|
21
21
|
import { join } from "path";
|
|
22
|
-
import
|
|
22
|
+
import React7 from "react";
|
|
23
23
|
import { Command } from "commander";
|
|
24
24
|
import { config } from "dotenv";
|
|
25
25
|
import { render } from "ink";
|
|
26
26
|
|
|
27
27
|
// src/components/App.tsx
|
|
28
|
-
import
|
|
29
|
-
import { Box as
|
|
28
|
+
import React6, { useState, useEffect, useRef } from "react";
|
|
29
|
+
import { Box as Box6, Text as Text6, useApp } from "ink";
|
|
30
30
|
import Gradient from "ink-gradient";
|
|
31
31
|
import Spinner from "ink-spinner";
|
|
32
32
|
|
|
33
|
+
// src/components/BestPractices.tsx
|
|
34
|
+
import React from "react";
|
|
35
|
+
import { Box, Text } from "ink";
|
|
36
|
+
function BestPractices({ report }) {
|
|
37
|
+
const recs = report.recommendations;
|
|
38
|
+
if (!recs || recs.length === 0) return null;
|
|
39
|
+
const sorted = [...recs].sort((a, b) => {
|
|
40
|
+
const order = { recommend: 0, suggest: 1 };
|
|
41
|
+
return order[a.severity] - order[b.severity];
|
|
42
|
+
});
|
|
43
|
+
const display = sorted.slice(0, 5);
|
|
44
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "\u{1F4A1} Advisor:"), display.map((rec) => /* @__PURE__ */ React.createElement(Box, { key: rec.id, marginLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: rec.severity === "recommend" ? "yellow" : "gray" }, rec.severity === "recommend" ? "\u25CF " : "\u25CB "), /* @__PURE__ */ React.createElement(Text, { bold: true }, rec.title), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " \u2014 ", rec.message))));
|
|
45
|
+
}
|
|
46
|
+
|
|
33
47
|
// src/components/CheckResult.tsx
|
|
34
|
-
import
|
|
35
|
-
import { Box as
|
|
48
|
+
import React3 from "react";
|
|
49
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
36
50
|
|
|
37
51
|
// src/components/ScoreBar.tsx
|
|
38
|
-
import
|
|
39
|
-
import { Box, Text } from "ink";
|
|
52
|
+
import React2 from "react";
|
|
53
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
40
54
|
function ScoreBar({ score, width = 20 }) {
|
|
41
55
|
const filled = Math.round(score / 100 * width);
|
|
42
56
|
const empty = width - filled;
|
|
43
57
|
const color = score >= 80 ? "green" : score >= 60 ? "yellow" : "red";
|
|
44
|
-
return /* @__PURE__ */
|
|
58
|
+
return /* @__PURE__ */ React2.createElement(Box2, null, /* @__PURE__ */ React2.createElement(Text2, { color }, "\u2588".repeat(filled)), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "\u2591".repeat(empty)), /* @__PURE__ */ React2.createElement(Text2, { color }, " ", score, "/100"));
|
|
45
59
|
}
|
|
46
60
|
|
|
47
61
|
// src/components/CheckResult.tsx
|
|
@@ -61,20 +75,20 @@ var CATEGORY_ICONS = {
|
|
|
61
75
|
function CheckResultRow({ result }) {
|
|
62
76
|
const statusColor = result.status === "pass" ? "green" : result.status === "fail" ? "red" : result.status === "skipped" ? "gray" : "yellow";
|
|
63
77
|
const icon = CATEGORY_ICONS[result.category] ?? "\u2022";
|
|
64
|
-
return /* @__PURE__ */
|
|
65
|
-
|
|
78
|
+
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, null, icon, " "), /* @__PURE__ */ React3.createElement(Text3, { bold: true }, result.name), /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " via ", result.toolsUsed.join(", "))), /* @__PURE__ */ React3.createElement(Box3, { marginLeft: 2 }, /* @__PURE__ */ React3.createElement(ScoreBar, { score: result.score, width: 16 }), /* @__PURE__ */ React3.createElement(Text3, { color: statusColor }, " ", STATUS_ICONS[result.status], " ", result.status)), result.issues.slice(0, 3).map((issue) => /* @__PURE__ */ React3.createElement(Box3, { key: `${issue.severity}-${issue.message}`, marginLeft: 2 }, /* @__PURE__ */ React3.createElement(
|
|
79
|
+
Text3,
|
|
66
80
|
{
|
|
67
81
|
color: issue.severity === "critical" ? "red" : issue.severity === "warning" ? "yellow" : "gray"
|
|
68
82
|
},
|
|
69
83
|
issue.severity === "critical" ? " \u2717" : issue.severity === "warning" ? " \u26A0" : " \u2139",
|
|
70
84
|
" ",
|
|
71
85
|
issue.message
|
|
72
|
-
))), result.issues.length > 3 && /* @__PURE__ */
|
|
86
|
+
))), result.issues.length > 3 && /* @__PURE__ */ React3.createElement(Box3, { marginLeft: 4 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "... and ", result.issues.length - 3, " more")));
|
|
73
87
|
}
|
|
74
88
|
|
|
75
89
|
// src/components/QuickWins.tsx
|
|
76
|
-
import
|
|
77
|
-
import { Box as
|
|
90
|
+
import React4 from "react";
|
|
91
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
78
92
|
function replacePackageManager(cmd, pm) {
|
|
79
93
|
if (pm === "npm") return cmd;
|
|
80
94
|
const install = pm === "pnpm" ? "pnpm add" : pm === "yarn" ? "yarn add" : "bun add";
|
|
@@ -90,12 +104,12 @@ function QuickWins({ report }) {
|
|
|
90
104
|
return order[a.severity] - order[b.severity];
|
|
91
105
|
}).slice(0, 5);
|
|
92
106
|
if (fixes.length === 0) return null;
|
|
93
|
-
return /* @__PURE__ */
|
|
107
|
+
return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text4, { bold: true }, "\u{1F525} Quick Wins:"), fixes.map((fix) => /* @__PURE__ */ React4.createElement(Box4, { key: `${fix.severity}-${fix.message}`, marginLeft: 2 }, /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, "\u2192 "), /* @__PURE__ */ React4.createElement(Text4, null, fix.fix.description), fix.fix.command && /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, ": ", replacePackageManager(fix.fix.command, pm)))));
|
|
94
108
|
}
|
|
95
109
|
|
|
96
110
|
// src/components/Summary.tsx
|
|
97
|
-
import
|
|
98
|
-
import { Box as
|
|
111
|
+
import React5 from "react";
|
|
112
|
+
import { Box as Box5, Text as Text5 } from "ink";
|
|
99
113
|
function formatDuration(ms) {
|
|
100
114
|
if (ms < 1e3) return `${ms}ms`;
|
|
101
115
|
const seconds = ms / 1e3;
|
|
@@ -105,7 +119,7 @@ function formatDuration(ms) {
|
|
|
105
119
|
return `${minutes}m ${remainingSeconds}s`;
|
|
106
120
|
}
|
|
107
121
|
function Summary({ report, scanDuration }) {
|
|
108
|
-
return /* @__PURE__ */
|
|
122
|
+
return /* @__PURE__ */ React5.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "\u2501".repeat(52)), /* @__PURE__ */ React5.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text5, { bold: true }, "Overall Health Score: "), /* @__PURE__ */ React5.createElement(ScoreBar, { score: report.overallScore, width: 12 }), /* @__PURE__ */ React5.createElement(Text5, null, " ", getScoreEmoji(report.overallScore)), scanDuration != null && /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, " ", formatDuration(scanDuration))), /* @__PURE__ */ React5.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "red" }, " \u2717 ", report.summary.critical, " critical"), /* @__PURE__ */ React5.createElement(Text5, { color: "yellow" }, " \u26A0 ", report.summary.warnings, " warnings"), /* @__PURE__ */ React5.createElement(Text5, { color: "gray" }, " i ", report.summary.info, " info")), report.quote && /* @__PURE__ */ React5.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text5, { italic: true, dimColor: true }, '"', report.quote.text, '"'), /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, " \u2014 ", report.quote.source)), report.config?.hasCustomConfig && /* @__PURE__ */ React5.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text5, { dimColor: true, italic: true }, "Custom config active", report.config.disabledChecks.length > 0 && ` (${report.config.disabledChecks.length} check${report.config.disabledChecks.length === 1 ? "" : "s"} disabled)`)));
|
|
109
123
|
}
|
|
110
124
|
|
|
111
125
|
// src/components/App.tsx
|
|
@@ -176,7 +190,7 @@ function App({
|
|
|
176
190
|
setMonorepoReport(r);
|
|
177
191
|
setProjectName(`monorepo (${r.packages.length} packages)`);
|
|
178
192
|
try {
|
|
179
|
-
const { getDependencyTree } = await import("./dist-
|
|
193
|
+
const { getDependencyTree } = await import("./dist-CEJKDCQM.js");
|
|
180
194
|
const { saveDepTree } = await import("./history-XLNVZEDI.js");
|
|
181
195
|
const packages = {};
|
|
182
196
|
for (const pkg of r.packages) {
|
|
@@ -188,7 +202,7 @@ function App({
|
|
|
188
202
|
if (openWeb) {
|
|
189
203
|
setPhase("opening-web");
|
|
190
204
|
try {
|
|
191
|
-
const { serveWeb } = await import("./web-
|
|
205
|
+
const { serveWeb } = await import("./web-KRYFOBSH.js");
|
|
192
206
|
const { default: openBrowser } = await import("open");
|
|
193
207
|
let aiService;
|
|
194
208
|
if (enableAI && process.env.ANTHROPIC_API_KEY) {
|
|
@@ -245,7 +259,7 @@ function App({
|
|
|
245
259
|
} catch {
|
|
246
260
|
}
|
|
247
261
|
try {
|
|
248
|
-
const { getDependencyTree } = await import("./dist-
|
|
262
|
+
const { getDependencyTree } = await import("./dist-CEJKDCQM.js");
|
|
249
263
|
const { saveDepTree } = await import("./history-XLNVZEDI.js");
|
|
250
264
|
const tree = await getDependencyTree(projectPath, r.projectInfo.packageManager);
|
|
251
265
|
saveDepTree(projectPath, tree);
|
|
@@ -254,7 +268,7 @@ function App({
|
|
|
254
268
|
if (openWeb) {
|
|
255
269
|
setPhase("opening-web");
|
|
256
270
|
try {
|
|
257
|
-
const { serveWeb } = await import("./web-
|
|
271
|
+
const { serveWeb } = await import("./web-KRYFOBSH.js");
|
|
258
272
|
const { default: openBrowser } = await import("open");
|
|
259
273
|
let aiService;
|
|
260
274
|
if (enableAI && process.env.ANTHROPIC_API_KEY) {
|
|
@@ -280,20 +294,20 @@ function App({
|
|
|
280
294
|
setTimeout(() => exit(err), 100);
|
|
281
295
|
});
|
|
282
296
|
}, []);
|
|
283
|
-
return /* @__PURE__ */
|
|
297
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React6.createElement(Header, { projectName }), updateInfo && /* @__PURE__ */ React6.createElement(
|
|
284
298
|
UpdateNotice,
|
|
285
299
|
{
|
|
286
300
|
currentVersion: updateInfo.currentVersion,
|
|
287
301
|
latestVersion: updateInfo.latestVersion
|
|
288
302
|
}
|
|
289
|
-
), phase === "loading" && /* @__PURE__ */
|
|
303
|
+
), phase === "loading" && /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, isMonorepo ? /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "magenta" }, /* @__PURE__ */ React6.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " ", LOADING_MESSAGES[loadingMsgIdx])), scanningPackage && /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, marginLeft: 2 }, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\u2192 "), /* @__PURE__ */ React6.createElement(Text6, { color: "cyan" }, scanningPackage))) : /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "Running health checks..."), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, marginLeft: 2 }, /* @__PURE__ */ React6.createElement(ProgressList, { items: progress })))), phase === "error" && /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "red" }, "\u2717 Error: ", error)), phase === "results" && monorepoReport && /* @__PURE__ */ React6.createElement(MonorepoSummaryTable, { report: monorepoReport, scanDuration }), phase === "results" && report && /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, report.checks.filter((c) => c.status !== "skipped").map((check) => /* @__PURE__ */ React6.createElement(CheckResultRow, { key: check.id, result: check })), /* @__PURE__ */ React6.createElement(Summary, { report, scanDuration }), /* @__PURE__ */ React6.createElement(QuickWins, { report }), /* @__PURE__ */ React6.createElement(BestPractices, { report }), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "View detailed report: "), /* @__PURE__ */ React6.createElement(Text6, { color: "cyan" }, "sickbay --web"))), phase === "opening-web" && (monorepoReport ?? report) && /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, monorepoReport ? /* @__PURE__ */ React6.createElement(MonorepoSummaryTable, { report: monorepoReport, scanDuration }) : report ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, report.checks.filter((c) => c.status !== "skipped").map((check) => /* @__PURE__ */ React6.createElement(CheckResultRow, { key: check.id, result: check })), /* @__PURE__ */ React6.createElement(Summary, { report, scanDuration })) : null, /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, webUrl ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green" }, "\u2713 Dashboard running at "), /* @__PURE__ */ React6.createElement(Text6, { color: "cyan" }, webUrl), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " (Ctrl+C to stop)")) : /* @__PURE__ */ React6.createElement(Text6, null, /* @__PURE__ */ React6.createElement(Text6, { color: "magenta" }, /* @__PURE__ */ React6.createElement(Spinner, { type: "dots" })), " ", /* @__PURE__ */ React6.createElement(Gradient, { name: "retro" }, "Launching dashboard with AI insights...")))));
|
|
290
304
|
}
|
|
291
305
|
function MonorepoSummaryTable({
|
|
292
306
|
report,
|
|
293
307
|
scanDuration
|
|
294
308
|
}) {
|
|
295
309
|
const scoreColor = (score) => score >= 80 ? "green" : score >= 60 ? "yellow" : "red";
|
|
296
|
-
return /* @__PURE__ */
|
|
310
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Box6, { marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "Monorepo \xB7 "), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, report.monorepoType, " workspaces \xB7 "), /* @__PURE__ */ React6.createElement(Text6, null, report.packages.length, " packages")), report.packages.map((pkg) => /* @__PURE__ */ React6.createElement(Box6, { key: pkg.path, marginLeft: 2, gap: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: scoreColor(pkg.score) }, scoreBar(pkg.score)), /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: scoreColor(pkg.score) }, String(pkg.score).padStart(3)), /* @__PURE__ */ React6.createElement(Text6, null, pkg.name), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, pkg.framework), pkg.summary.critical > 0 && /* @__PURE__ */ React6.createElement(Text6, { color: "red" }, " ", pkg.summary.critical, " critical"))), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, gap: 2 }, /* @__PURE__ */ React6.createElement(Text6, { bold: true }, "Overall: "), /* @__PURE__ */ React6.createElement(Text6, { color: scoreColor(report.overallScore), bold: true }, report.overallScore), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\xB7 "), /* @__PURE__ */ React6.createElement(Text6, { color: "red" }, report.summary.critical, " critical"), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\xB7 "), /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, report.summary.warnings, " warnings"), scanDuration !== null && /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\xB7 "), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, formatDuration2(scanDuration)))), report.quote && /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { italic: true, dimColor: true }, '"', report.quote.text, '"'), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \u2014 ", report.quote.source)), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "Per-package details: "), /* @__PURE__ */ React6.createElement(Text6, { color: "cyan" }, "sickbay --web")));
|
|
297
311
|
}
|
|
298
312
|
|
|
299
313
|
// src/index.ts
|
|
@@ -303,7 +317,7 @@ if (existsSync(globalConfigPath)) {
|
|
|
303
317
|
}
|
|
304
318
|
config({ debug: false, quiet: true });
|
|
305
319
|
var program = new Command();
|
|
306
|
-
program.name("sickbay").description("React project health check CLI").version("1.15.
|
|
320
|
+
program.name("sickbay").description("React project health check CLI").version("1.15.2", "-v, --version").enablePositionalOptions().passThroughOptions().option("-p, --path <path>", "project path to analyze", process.cwd()).option("-c, --checks <checks>", "comma-separated list of checks to run").option("--package <name>", "scope to a single named package (monorepo only)").option("--json", "output raw JSON report").option("--web", "open web dashboard after scan").option("--no-ai", "disable AI features").option("--no-quotes", "suppress personality quotes in output").option("--verbose", "show verbose output").action(async (options) => {
|
|
307
321
|
if (options.path && options.path !== process.cwd()) {
|
|
308
322
|
const projectEnvPath = join(options.path, ".env");
|
|
309
323
|
if (existsSync(projectEnvPath)) {
|
|
@@ -313,13 +327,13 @@ program.name("sickbay").description("React project health check CLI").version("1
|
|
|
313
327
|
const updatePromise = (async () => {
|
|
314
328
|
try {
|
|
315
329
|
const { checkForUpdate } = await import("./update-check-M7IFOMLJ.js");
|
|
316
|
-
return await checkForUpdate("1.15.
|
|
330
|
+
return await checkForUpdate("1.15.2");
|
|
317
331
|
} catch {
|
|
318
332
|
return null;
|
|
319
333
|
}
|
|
320
334
|
})();
|
|
321
335
|
const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
|
|
322
|
-
const { detectMonorepo, runSickbay: runSickbay2, runSickbayMonorepo: runSickbayMonorepo2 } = await import("./dist-
|
|
336
|
+
const { detectMonorepo, runSickbay: runSickbay2, runSickbayMonorepo: runSickbayMonorepo2 } = await import("./dist-CEJKDCQM.js");
|
|
323
337
|
const monorepoInfo = await detectMonorepo(options.path);
|
|
324
338
|
if (options.package && monorepoInfo.isMonorepo) {
|
|
325
339
|
const { readFileSync } = await import("fs");
|
|
@@ -347,7 +361,7 @@ program.name("sickbay").description("React project health check CLI").version("1
|
|
|
347
361
|
process.exit(0);
|
|
348
362
|
}
|
|
349
363
|
render(
|
|
350
|
-
|
|
364
|
+
React7.createElement(App, {
|
|
351
365
|
projectPath: targetPath,
|
|
352
366
|
checks,
|
|
353
367
|
openWeb: options.web,
|
|
@@ -383,7 +397,7 @@ program.name("sickbay").description("React project health check CLI").version("1
|
|
|
383
397
|
} catch {
|
|
384
398
|
}
|
|
385
399
|
try {
|
|
386
|
-
const { getDependencyTree } = await import("./dist-
|
|
400
|
+
const { getDependencyTree } = await import("./dist-CEJKDCQM.js");
|
|
387
401
|
const { saveDepTree } = await import("./history-XLNVZEDI.js");
|
|
388
402
|
const tree = await getDependencyTree(options.path, report.projectInfo.packageManager);
|
|
389
403
|
saveDepTree(options.path, tree);
|
|
@@ -393,7 +407,7 @@ program.name("sickbay").description("React project health check CLI").version("1
|
|
|
393
407
|
process.exit(0);
|
|
394
408
|
}
|
|
395
409
|
render(
|
|
396
|
-
|
|
410
|
+
React7.createElement(App, {
|
|
397
411
|
projectPath: options.path,
|
|
398
412
|
checks,
|
|
399
413
|
openWeb: options.web,
|
|
@@ -410,16 +424,16 @@ program.command("init").description("Initialize .sickbay/ folder and run an init
|
|
|
410
424
|
"add newly available checks to existing config without touching existing entries"
|
|
411
425
|
).option("--reset-config", "regenerate config from scratch (overwrites existing)").action(async (options) => {
|
|
412
426
|
if (options.resetConfig) {
|
|
413
|
-
const { generateConfigFile } = await import("./init-
|
|
427
|
+
const { generateConfigFile } = await import("./init-WGMAAQSO.js");
|
|
414
428
|
await generateConfigFile(options.path, { force: true });
|
|
415
429
|
return;
|
|
416
430
|
}
|
|
417
431
|
if (options.sync) {
|
|
418
|
-
const { syncConfigFile } = await import("./init-
|
|
432
|
+
const { syncConfigFile } = await import("./init-WGMAAQSO.js");
|
|
419
433
|
await syncConfigFile(options.path);
|
|
420
434
|
return;
|
|
421
435
|
}
|
|
422
|
-
const { initSickbay } = await import("./init-
|
|
436
|
+
const { initSickbay } = await import("./init-WGMAAQSO.js");
|
|
423
437
|
await initSickbay(options.path);
|
|
424
438
|
});
|
|
425
439
|
program.command("fix").description("Interactively fix issues found by sickbay scan").option("-p, --path <path>", "project path to analyze", process.cwd()).option("-c, --checks <checks>", "comma-separated list of checks to run").option("--package <name>", "scope to a single package (monorepo only)").option("--all", "apply all available fixes without prompting").option("--dry-run", "show what would be fixed without executing").option("--verbose", "show verbose output").action(async (options) => {
|
|
@@ -429,13 +443,13 @@ program.command("fix").description("Interactively fix issues found by sickbay sc
|
|
|
429
443
|
config({ path: projectEnvPath, override: true });
|
|
430
444
|
}
|
|
431
445
|
}
|
|
432
|
-
const { resolveProject } = await import("./resolve-package-
|
|
446
|
+
const { resolveProject } = await import("./resolve-package-FYX3J6PS.js");
|
|
433
447
|
const resolution = await resolveProject(options.path, options.package);
|
|
434
|
-
const { FixApp } = await import("./FixApp-
|
|
448
|
+
const { FixApp } = await import("./FixApp-HT7PHJKO.js");
|
|
435
449
|
const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
|
|
436
450
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
437
451
|
render(
|
|
438
|
-
|
|
452
|
+
React7.createElement(FixApp, {
|
|
439
453
|
projectPath,
|
|
440
454
|
checks,
|
|
441
455
|
applyAll: options.all ?? false,
|
|
@@ -454,12 +468,12 @@ program.command("trend").description("Show score history and trends over time").
|
|
|
454
468
|
config({ path: projectEnvPath, override: true });
|
|
455
469
|
}
|
|
456
470
|
}
|
|
457
|
-
const { resolveProject } = await import("./resolve-package-
|
|
471
|
+
const { resolveProject } = await import("./resolve-package-FYX3J6PS.js");
|
|
458
472
|
const resolution = await resolveProject(options.path, options.package);
|
|
459
473
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
460
|
-
const { TrendApp } = await import("./TrendApp-
|
|
474
|
+
const { TrendApp } = await import("./TrendApp-CB7CNPZI.js");
|
|
461
475
|
render(
|
|
462
|
-
|
|
476
|
+
React7.createElement(TrendApp, {
|
|
463
477
|
projectPath,
|
|
464
478
|
last: parseInt(options.last, 10),
|
|
465
479
|
jsonOutput: options.json ?? false,
|
|
@@ -476,12 +490,12 @@ program.command("stats").description("Show a quick codebase overview and project
|
|
|
476
490
|
config({ path: projectEnvPath, override: true });
|
|
477
491
|
}
|
|
478
492
|
}
|
|
479
|
-
const { resolveProject } = await import("./resolve-package-
|
|
493
|
+
const { resolveProject } = await import("./resolve-package-FYX3J6PS.js");
|
|
480
494
|
const resolution = await resolveProject(options.path, options.package);
|
|
481
495
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
482
|
-
const { StatsApp } = await import("./StatsApp-
|
|
496
|
+
const { StatsApp } = await import("./StatsApp-GOCP43YN.js");
|
|
483
497
|
render(
|
|
484
|
-
|
|
498
|
+
React7.createElement(StatsApp, {
|
|
485
499
|
projectPath,
|
|
486
500
|
jsonOutput: options.json ?? false,
|
|
487
501
|
isMonorepo: resolution.isMonorepo && !resolution.targetPath,
|
|
@@ -491,10 +505,10 @@ program.command("stats").description("Show a quick codebase overview and project
|
|
|
491
505
|
);
|
|
492
506
|
});
|
|
493
507
|
program.command("tui").description("Launch the persistent developer dashboard").option("-p, --path <path>", "project path to monitor", process.cwd()).option("--no-watch", "disable file-watching auto-refresh").option("--no-quotes", "suppress personality quotes in output").option("--refresh <seconds>", "auto-refresh interval in seconds", "300").option("-c, --checks <checks>", "comma-separated list of checks to run").action(async (options) => {
|
|
494
|
-
const { TuiApp } = await import("./TuiApp-
|
|
508
|
+
const { TuiApp } = await import("./TuiApp-SX22YRN7.js");
|
|
495
509
|
const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
|
|
496
510
|
render(
|
|
497
|
-
|
|
511
|
+
React7.createElement(TuiApp, {
|
|
498
512
|
projectPath: options.path,
|
|
499
513
|
checks,
|
|
500
514
|
watchEnabled: options.watch !== false,
|
|
@@ -511,12 +525,12 @@ program.command("doctor").description("Diagnose project setup and configuration
|
|
|
511
525
|
config({ path: projectEnvPath, override: true });
|
|
512
526
|
}
|
|
513
527
|
}
|
|
514
|
-
const { resolveProject } = await import("./resolve-package-
|
|
528
|
+
const { resolveProject } = await import("./resolve-package-FYX3J6PS.js");
|
|
515
529
|
const resolution = await resolveProject(options.path, options.package);
|
|
516
530
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
517
|
-
const { DoctorApp } = await import("./DoctorApp-
|
|
531
|
+
const { DoctorApp } = await import("./DoctorApp-VIDISA3A.js");
|
|
518
532
|
render(
|
|
519
|
-
|
|
533
|
+
React7.createElement(DoctorApp, {
|
|
520
534
|
projectPath,
|
|
521
535
|
autoFix: options.fix ?? false,
|
|
522
536
|
jsonOutput: options.json ?? false,
|
|
@@ -527,13 +541,13 @@ program.command("doctor").description("Diagnose project setup and configuration
|
|
|
527
541
|
);
|
|
528
542
|
});
|
|
529
543
|
program.command("badge").description("Generate a health score badge for your README").option("-p, --path <path>", "project path", process.cwd()).option("--package <name>", "scope to a single package (monorepo only)").option("--html", "output HTML <img> tag instead of markdown").option("--url", "output bare badge URL only").option("--label <text>", "custom badge label", "sickbay").option("--scan", "run a fresh scan instead of using last report").action(async (options) => {
|
|
530
|
-
const { resolveProject } = await import("./resolve-package-
|
|
544
|
+
const { resolveProject } = await import("./resolve-package-FYX3J6PS.js");
|
|
531
545
|
const resolution = await resolveProject(options.path, options.package);
|
|
532
546
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
533
547
|
const { loadScoreFromLastReport, badgeUrl, badgeMarkdown, badgeHtml } = await import("./badge-KQ73KEIN.js");
|
|
534
548
|
let score = options.scan ? null : loadScoreFromLastReport(projectPath);
|
|
535
549
|
if (score === null) {
|
|
536
|
-
const { runSickbay: runSickbay2 } = await import("./dist-
|
|
550
|
+
const { runSickbay: runSickbay2 } = await import("./dist-CEJKDCQM.js");
|
|
537
551
|
const report = await runSickbay2({ projectPath, quotes: false });
|
|
538
552
|
try {
|
|
539
553
|
const { saveEntry, saveLastReport } = await import("./history-XLNVZEDI.js");
|
|
@@ -566,9 +580,9 @@ program.command("diff <branch>").description("Compare health score against anoth
|
|
|
566
580
|
}
|
|
567
581
|
}
|
|
568
582
|
const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
|
|
569
|
-
const { DiffApp } = await import("./DiffApp-
|
|
583
|
+
const { DiffApp } = await import("./DiffApp-M3D3HGI4.js");
|
|
570
584
|
render(
|
|
571
|
-
|
|
585
|
+
React7.createElement(DiffApp, {
|
|
572
586
|
projectPath: options.path,
|
|
573
587
|
branch,
|
|
574
588
|
jsonOutput: options.json ?? false,
|
|
@@ -106,7 +106,7 @@ async function serveWeb(report, preferredPort = 3030, aiService) {
|
|
|
106
106
|
if (url === "/sickbay-config.json") {
|
|
107
107
|
const basePath = "isMonorepo" in report ? report.rootPath : report.projectPath;
|
|
108
108
|
try {
|
|
109
|
-
const { loadConfig } = await import("./dist-
|
|
109
|
+
const { loadConfig } = await import("./dist-CEJKDCQM.js");
|
|
110
110
|
const config = await loadConfig(basePath);
|
|
111
111
|
if (config) {
|
|
112
112
|
res.writeHead(200, { "Content-Type": "application/json" });
|