sickbay 1.10.0 → 1.10.2
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-S7MJHZ5R.js → DiffApp-EVE2JSUW.js} +1 -1
- package/dist/{DoctorApp-DLQDDX6W.js → DoctorApp-JXY4Z5JV.js} +1 -1
- package/dist/{FixApp-SDNC4KU6.js → FixApp-AJU53CXH.js} +1 -1
- package/dist/{StatsApp-AWV2NQLZ.js → StatsApp-VN5E3TWE.js} +1 -1
- package/dist/{TrendApp-JVJ5XDC2.js → TrendApp-DHCUH6JE.js} +1 -1
- package/dist/{TuiApp-DKMQAUFR.js → TuiApp-X7RS5NV6.js} +1 -1
- package/dist/{chunk-5HKR3PSR.js → chunk-C7GKIF4V.js} +1 -1
- package/dist/index.js +12 -12
- package/dist/{init-SLYPRBUB.js → init-RJDFIHJD.js} +44 -13
- package/package.json +1 -1
|
@@ -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.
|
|
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.10.1")), 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/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-TYG7ZQBP.js";
|
|
9
9
|
import {
|
|
10
10
|
Header
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-C7GKIF4V.js";
|
|
12
12
|
import {
|
|
13
13
|
getScoreEmoji,
|
|
14
14
|
runSickbay,
|
|
@@ -304,7 +304,7 @@ if (existsSync(globalConfigPath)) {
|
|
|
304
304
|
}
|
|
305
305
|
config({ debug: false, quiet: true });
|
|
306
306
|
var program = new Command();
|
|
307
|
-
program.name("sickbay").description("React project health check CLI").version("1.
|
|
307
|
+
program.name("sickbay").description("React project health check CLI").version("1.10.1", "-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) => {
|
|
308
308
|
if (options.path && options.path !== process.cwd()) {
|
|
309
309
|
const projectEnvPath = join(options.path, ".env");
|
|
310
310
|
if (existsSync(projectEnvPath)) {
|
|
@@ -314,7 +314,7 @@ program.name("sickbay").description("React project health check CLI").version("1
|
|
|
314
314
|
const updatePromise = (async () => {
|
|
315
315
|
try {
|
|
316
316
|
const { checkForUpdate } = await import("./update-check-QLG6GA4Z.js");
|
|
317
|
-
return await checkForUpdate("1.
|
|
317
|
+
return await checkForUpdate("1.10.1");
|
|
318
318
|
} catch {
|
|
319
319
|
return null;
|
|
320
320
|
}
|
|
@@ -411,16 +411,16 @@ program.command("init").description("Initialize .sickbay/ folder and run an init
|
|
|
411
411
|
"add newly available checks to existing config without touching existing entries"
|
|
412
412
|
).option("--reset-config", "regenerate config from scratch (overwrites existing)").action(async (options) => {
|
|
413
413
|
if (options.resetConfig) {
|
|
414
|
-
const { generateConfigFile } = await import("./init-
|
|
414
|
+
const { generateConfigFile } = await import("./init-RJDFIHJD.js");
|
|
415
415
|
await generateConfigFile(options.path, { force: true });
|
|
416
416
|
return;
|
|
417
417
|
}
|
|
418
418
|
if (options.sync) {
|
|
419
|
-
const { syncConfigFile } = await import("./init-
|
|
419
|
+
const { syncConfigFile } = await import("./init-RJDFIHJD.js");
|
|
420
420
|
await syncConfigFile(options.path);
|
|
421
421
|
return;
|
|
422
422
|
}
|
|
423
|
-
const { initSickbay } = await import("./init-
|
|
423
|
+
const { initSickbay } = await import("./init-RJDFIHJD.js");
|
|
424
424
|
await initSickbay(options.path);
|
|
425
425
|
});
|
|
426
426
|
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) => {
|
|
@@ -432,7 +432,7 @@ program.command("fix").description("Interactively fix issues found by sickbay sc
|
|
|
432
432
|
}
|
|
433
433
|
const { resolveProject } = await import("./resolve-package-HXEADBCX.js");
|
|
434
434
|
const resolution = await resolveProject(options.path, options.package);
|
|
435
|
-
const { FixApp } = await import("./FixApp-
|
|
435
|
+
const { FixApp } = await import("./FixApp-AJU53CXH.js");
|
|
436
436
|
const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
|
|
437
437
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
438
438
|
render(
|
|
@@ -458,7 +458,7 @@ program.command("trend").description("Show score history and trends over time").
|
|
|
458
458
|
const { resolveProject } = await import("./resolve-package-HXEADBCX.js");
|
|
459
459
|
const resolution = await resolveProject(options.path, options.package);
|
|
460
460
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
461
|
-
const { TrendApp } = await import("./TrendApp-
|
|
461
|
+
const { TrendApp } = await import("./TrendApp-DHCUH6JE.js");
|
|
462
462
|
render(
|
|
463
463
|
React6.createElement(TrendApp, {
|
|
464
464
|
projectPath,
|
|
@@ -480,7 +480,7 @@ program.command("stats").description("Show a quick codebase overview and project
|
|
|
480
480
|
const { resolveProject } = await import("./resolve-package-HXEADBCX.js");
|
|
481
481
|
const resolution = await resolveProject(options.path, options.package);
|
|
482
482
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
483
|
-
const { StatsApp } = await import("./StatsApp-
|
|
483
|
+
const { StatsApp } = await import("./StatsApp-VN5E3TWE.js");
|
|
484
484
|
render(
|
|
485
485
|
React6.createElement(StatsApp, {
|
|
486
486
|
projectPath,
|
|
@@ -492,7 +492,7 @@ program.command("stats").description("Show a quick codebase overview and project
|
|
|
492
492
|
);
|
|
493
493
|
});
|
|
494
494
|
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) => {
|
|
495
|
-
const { TuiApp } = await import("./TuiApp-
|
|
495
|
+
const { TuiApp } = await import("./TuiApp-X7RS5NV6.js");
|
|
496
496
|
const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
|
|
497
497
|
render(
|
|
498
498
|
React6.createElement(TuiApp, {
|
|
@@ -515,7 +515,7 @@ program.command("doctor").description("Diagnose project setup and configuration
|
|
|
515
515
|
const { resolveProject } = await import("./resolve-package-HXEADBCX.js");
|
|
516
516
|
const resolution = await resolveProject(options.path, options.package);
|
|
517
517
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
518
|
-
const { DoctorApp } = await import("./DoctorApp-
|
|
518
|
+
const { DoctorApp } = await import("./DoctorApp-JXY4Z5JV.js");
|
|
519
519
|
render(
|
|
520
520
|
React6.createElement(DoctorApp, {
|
|
521
521
|
projectPath,
|
|
@@ -563,7 +563,7 @@ program.command("diff <branch>").description("Compare health score against anoth
|
|
|
563
563
|
}
|
|
564
564
|
}
|
|
565
565
|
const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
|
|
566
|
-
const { DiffApp } = await import("./DiffApp-
|
|
566
|
+
const { DiffApp } = await import("./DiffApp-EVE2JSUW.js");
|
|
567
567
|
render(
|
|
568
568
|
React6.createElement(DiffApp, {
|
|
569
569
|
projectPath: options.path,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectContext,
|
|
3
|
+
detectMonorepo,
|
|
3
4
|
getAvailableChecks,
|
|
4
|
-
runSickbay
|
|
5
|
+
runSickbay,
|
|
6
|
+
runSickbayMonorepo
|
|
5
7
|
} from "./chunk-BVDAUF7Y.js";
|
|
6
8
|
import {
|
|
7
9
|
saveEntry
|
|
@@ -20,14 +22,32 @@ var CATEGORY_LABELS = {
|
|
|
20
22
|
security: "Security",
|
|
21
23
|
git: "Git"
|
|
22
24
|
};
|
|
25
|
+
async function getAllApplicableChecks(projectPath, monorepoInfo) {
|
|
26
|
+
const mono = monorepoInfo ?? await detectMonorepo(projectPath);
|
|
27
|
+
if (!mono.isMonorepo) {
|
|
28
|
+
const context = await detectContext(projectPath);
|
|
29
|
+
return getAvailableChecks(context);
|
|
30
|
+
}
|
|
31
|
+
const seen = /* @__PURE__ */ new Set();
|
|
32
|
+
const allChecks = [];
|
|
33
|
+
for (const pkgPath of mono.packagePaths) {
|
|
34
|
+
const context = await detectContext(pkgPath);
|
|
35
|
+
for (const check of getAvailableChecks(context)) {
|
|
36
|
+
if (!seen.has(check.name)) {
|
|
37
|
+
seen.add(check.name);
|
|
38
|
+
allChecks.push(check);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return allChecks;
|
|
43
|
+
}
|
|
23
44
|
async function generateConfigFile(projectPath, options) {
|
|
24
45
|
const configPath = join(projectPath, "sickbay.config.ts");
|
|
25
46
|
if (!options?.force && existsSync(configPath)) {
|
|
26
47
|
console.log("Config already exists, skipping");
|
|
27
48
|
return;
|
|
28
49
|
}
|
|
29
|
-
const
|
|
30
|
-
const checks = getAvailableChecks(context);
|
|
50
|
+
const checks = await getAllApplicableChecks(projectPath);
|
|
31
51
|
const grouped = {};
|
|
32
52
|
for (const check of checks) {
|
|
33
53
|
if (!grouped[check.category]) {
|
|
@@ -77,8 +97,7 @@ async function syncConfigFile(projectPath) {
|
|
|
77
97
|
);
|
|
78
98
|
return;
|
|
79
99
|
}
|
|
80
|
-
const
|
|
81
|
-
const applicableChecks = getAvailableChecks(context);
|
|
100
|
+
const applicableChecks = await getAllApplicableChecks(projectPath);
|
|
82
101
|
const existingIds = /* @__PURE__ */ new Set();
|
|
83
102
|
const checkPattern = /^\s*['"]?([\w-]+)['"]?\s*:/gm;
|
|
84
103
|
let match;
|
|
@@ -141,6 +160,7 @@ ${lines2.join("\n")}`);
|
|
|
141
160
|
console.log(`Added ${missing.length} new check(s): ${names}`);
|
|
142
161
|
}
|
|
143
162
|
async function initSickbay(projectPath) {
|
|
163
|
+
const monorepoInfo = await detectMonorepo(projectPath);
|
|
144
164
|
await generateConfigFile(projectPath);
|
|
145
165
|
const sickbayDir = join(projectPath, ".sickbay");
|
|
146
166
|
mkdirSync(sickbayDir, { recursive: true });
|
|
@@ -159,16 +179,27 @@ async function initSickbay(projectPath) {
|
|
|
159
179
|
console.log("\u26A0 .sickbay/baseline.json already exists. Overwriting with new scan.");
|
|
160
180
|
}
|
|
161
181
|
console.log("Running initial scan to generate baseline...\n");
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
182
|
+
let overallScore;
|
|
183
|
+
let projectName;
|
|
184
|
+
if (monorepoInfo.isMonorepo) {
|
|
185
|
+
const report = await runSickbayMonorepo({ projectPath, _config: null });
|
|
186
|
+
writeFileSync(baselinePath, JSON.stringify(report, null, 2));
|
|
187
|
+
overallScore = report.overallScore;
|
|
188
|
+
projectName = `monorepo (${report.packages.length} packages)`;
|
|
189
|
+
} else {
|
|
190
|
+
const report = await runSickbay({ projectPath, _config: null });
|
|
191
|
+
writeFileSync(baselinePath, JSON.stringify(report, null, 2));
|
|
192
|
+
try {
|
|
193
|
+
saveEntry(report);
|
|
194
|
+
} catch {
|
|
195
|
+
}
|
|
196
|
+
overallScore = report.overallScore;
|
|
197
|
+
projectName = report.projectInfo.name;
|
|
167
198
|
}
|
|
168
|
-
const scoreLabel =
|
|
199
|
+
const scoreLabel = overallScore >= 80 ? "good" : overallScore >= 60 ? "fair" : "needs work";
|
|
169
200
|
console.log(`
|
|
170
|
-
\u2713 Sickbay initialized for ${
|
|
171
|
-
console.log(` Overall score: ${
|
|
201
|
+
\u2713 Sickbay initialized for ${projectName}`);
|
|
202
|
+
console.log(` Overall score: ${overallScore}/100 (${scoreLabel})`);
|
|
172
203
|
console.log(`
|
|
173
204
|
Created:`);
|
|
174
205
|
console.log(` sickbay.config.ts \u2014 project configuration`);
|