react-doctor 0.0.25 → 0.0.26

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/cli.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
3
  import { execSync, spawn, spawnSync } from "node:child_process";
4
- import fs, { existsSync, mkdirSync, writeFileSync } from "node:fs";
5
- import os, { tmpdir } from "node:os";
4
+ import fs, { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
+ import os, { homedir, tmpdir } from "node:os";
6
6
  import path, { join } from "node:path";
7
7
  import { Command } from "commander";
8
8
  import { randomUUID } from "node:crypto";
@@ -29,6 +29,7 @@ const SCORE_API_URL = "https://www.react.doctor/api/score";
29
29
  const ESTIMATE_SCORE_API_URL = "https://www.react.doctor/api/estimate-score";
30
30
  const SHARE_BASE_URL = "https://www.react.doctor/share";
31
31
  const OPEN_BASE_URL = "https://www.react.doctor/open";
32
+ const INSTALL_SKILL_URL = "https://www.react.doctor/install-skill";
32
33
  const GIT_LS_FILES_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
33
34
  const OFFLINE_MESSAGE = "You are offline, could not calculate score. Reconnect to calculate.";
34
35
  const OFFLINE_FLAG_MESSAGE = "Score not calculated. Remove --offline to calculate score.";
@@ -1629,9 +1630,61 @@ const promptProjectSelection = async (workspacePackages, rootDirectory) => {
1629
1630
  return selectedDirectories;
1630
1631
  };
1631
1632
 
1633
+ //#endregion
1634
+ //#region src/utils/skill-prompt.ts
1635
+ const CONFIG_DIRECTORY = join(homedir(), ".react-doctor");
1636
+ const CONFIG_FILE = join(CONFIG_DIRECTORY, "config.json");
1637
+ const readSkillPromptConfig = () => {
1638
+ try {
1639
+ if (!existsSync(CONFIG_FILE)) return {};
1640
+ return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
1641
+ } catch {
1642
+ return {};
1643
+ }
1644
+ };
1645
+ const writeSkillPromptConfig = (config) => {
1646
+ try {
1647
+ if (!existsSync(CONFIG_DIRECTORY)) mkdirSync(CONFIG_DIRECTORY, { recursive: true });
1648
+ writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
1649
+ } catch {}
1650
+ };
1651
+ const installSkill = () => {
1652
+ try {
1653
+ execSync(`curl -fsSL ${INSTALL_SKILL_URL} | bash`, { stdio: "inherit" });
1654
+ } catch {
1655
+ logger.break();
1656
+ logger.dim("Skill install failed. You can install manually:");
1657
+ logger.dim(` curl -fsSL ${INSTALL_SKILL_URL} | bash`);
1658
+ }
1659
+ };
1660
+ const maybePromptSkillInstall = async (shouldSkipPrompts) => {
1661
+ const config = readSkillPromptConfig();
1662
+ if (config.skillPromptDismissed) return;
1663
+ if (shouldSkipPrompts) return;
1664
+ logger.break();
1665
+ logger.log(`${highlighter.info("💡")} Have your coding agent fix these issues automatically?`);
1666
+ logger.dim(` Install the ${highlighter.info("react-doctor")} skill to teach Cursor, Claude Code,`);
1667
+ logger.dim(" Ami, and other AI agents how to diagnose and fix React issues.");
1668
+ logger.break();
1669
+ const { shouldInstall } = await prompts({
1670
+ type: "confirm",
1671
+ name: "shouldInstall",
1672
+ message: "Install skill? (recommended)",
1673
+ initial: true
1674
+ });
1675
+ if (shouldInstall) {
1676
+ logger.break();
1677
+ installSkill();
1678
+ }
1679
+ writeSkillPromptConfig({
1680
+ ...config,
1681
+ skillPromptDismissed: true
1682
+ });
1683
+ };
1684
+
1632
1685
  //#endregion
1633
1686
  //#region src/cli.ts
1634
- const VERSION = "0.0.25";
1687
+ const VERSION = "0.0.26";
1635
1688
  const exitWithFixHint = () => {
1636
1689
  logger.break();
1637
1690
  logger.log("Cancelled.");
@@ -1730,7 +1783,10 @@ const program = new Command().name("react-doctor").description("Diagnose React c
1730
1783
  if (!isScoreOnly) logger.break();
1731
1784
  }
1732
1785
  if (flags.fix) openAmiToFix(resolvedDirectory);
1733
- if (!isScoreOnly && !shouldSkipAmiPrompts && !flags.fix) await maybePromptFix(resolvedDirectory, allDiagnostics, flags.offline ? null : await fetchEstimatedScore(allDiagnostics));
1786
+ if (!isScoreOnly && !shouldSkipAmiPrompts && !flags.fix) {
1787
+ await maybePromptSkillInstall(shouldSkipAmiPrompts);
1788
+ await maybePromptFix(resolvedDirectory, allDiagnostics, flags.offline ? null : await fetchEstimatedScore(allDiagnostics));
1789
+ }
1734
1790
  } catch (error) {
1735
1791
  handleError(error);
1736
1792
  }