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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Header
3
- } from "./chunk-5HKR3PSR.js";
3
+ } from "./chunk-C7GKIF4V.js";
4
4
  import "./chunk-JSBRDJBE.js";
5
5
 
6
6
  // src/components/DiffApp.tsx
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-4C42NVK3.js";
4
4
  import {
5
5
  Header
6
- } from "./chunk-5HKR3PSR.js";
6
+ } from "./chunk-C7GKIF4V.js";
7
7
  import {
8
8
  detectPackageManager,
9
9
  detectProject
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-MBVA75EM.js";
7
7
  import {
8
8
  Header
9
- } from "./chunk-5HKR3PSR.js";
9
+ } from "./chunk-C7GKIF4V.js";
10
10
  import {
11
11
  runSickbay
12
12
  } from "./chunk-BVDAUF7Y.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-4C42NVK3.js";
4
4
  import {
5
5
  Header
6
- } from "./chunk-5HKR3PSR.js";
6
+ } from "./chunk-C7GKIF4V.js";
7
7
  import {
8
8
  detectProject
9
9
  } from "./chunk-BVDAUF7Y.js";
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-4C42NVK3.js";
8
8
  import {
9
9
  Header
10
- } from "./chunk-5HKR3PSR.js";
10
+ } from "./chunk-C7GKIF4V.js";
11
11
  import "./chunk-BVDAUF7Y.js";
12
12
  import {
13
13
  detectRegressions,
@@ -690,7 +690,7 @@ function TuiApp({
690
690
  return () => timers.forEach(clearTimeout);
691
691
  }, []);
692
692
  useEffect7(() => {
693
- checkForUpdate("1.9.0").then((info) => {
693
+ checkForUpdate("1.10.1").then((info) => {
694
694
  if (info) setUpdateInfo(info);
695
695
  });
696
696
  }, []);
@@ -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.9.0")), projectName && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " Analyzing "), /* @__PURE__ */ React.createElement(Text, { bold: true, color: "white" }, 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.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-5HKR3PSR.js";
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.9.0", "-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
+ 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.9.0");
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-SLYPRBUB.js");
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-SLYPRBUB.js");
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-SLYPRBUB.js");
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-SDNC4KU6.js");
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-JVJ5XDC2.js");
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-AWV2NQLZ.js");
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-DKMQAUFR.js");
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-DLQDDX6W.js");
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-S7MJHZ5R.js");
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 context = await detectContext(projectPath);
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 context = await detectContext(projectPath);
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
- const report = await runSickbay({ projectPath, _config: null });
163
- writeFileSync(baselinePath, JSON.stringify(report, null, 2));
164
- try {
165
- saveEntry(report);
166
- } catch {
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 = report.overallScore >= 80 ? "good" : report.overallScore >= 60 ? "fair" : "needs work";
199
+ const scoreLabel = overallScore >= 80 ? "good" : overallScore >= 60 ? "fair" : "needs work";
169
200
  console.log(`
170
- \u2713 Sickbay initialized for ${report.projectInfo.name}`);
171
- console.log(` Overall score: ${report.overallScore}/100 (${scoreLabel})`);
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`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sickbay",
3
- "version": "1.10.0",
3
+ "version": "1.10.2",
4
4
  "description": "Zero-config health check CLI for JavaScript and TypeScript projects",
5
5
  "license": "MIT",
6
6
  "repository": {