react-doctor 0.0.20 → 0.0.21

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
@@ -28,8 +28,10 @@ const SUMMARY_BOX_HORIZONTAL_PADDING_CHARS = 1;
28
28
  const SUMMARY_BOX_OUTER_INDENT_CHARS = 2;
29
29
  const SCORE_API_URL = "https://www.react.doctor/api/score";
30
30
  const SHARE_BASE_URL = "https://www.react.doctor/share";
31
+ const OPEN_BASE_URL = "https://www.react.doctor/open";
31
32
  const GIT_LS_FILES_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
32
33
  const OFFLINE_MESSAGE = "You are offline, could not calculate score. Reconnect to calculate.";
34
+ const OFFLINE_FLAG_MESSAGE = "Score not calculated. Remove --offline to calculate score.";
33
35
  const DEFAULT_BRANCH_CANDIDATES = ["main", "master"];
34
36
 
35
37
  //#endregion
@@ -1212,7 +1214,7 @@ const buildShareUrl = (diagnostics, scoreResult, projectName) => {
1212
1214
  if (affectedFileCount > 0) params.set("f", String(affectedFileCount));
1213
1215
  return `${SHARE_BASE_URL}?${params.toString()}`;
1214
1216
  };
1215
- const printSummary = (diagnostics, elapsedMilliseconds, scoreResult, projectName, totalSourceFileCount) => {
1217
+ const printSummary = (diagnostics, elapsedMilliseconds, scoreResult, projectName, totalSourceFileCount, noScoreMessage) => {
1216
1218
  const errorCount = diagnostics.filter((diagnostic) => diagnostic.severity === "error").length;
1217
1219
  const warningCount = diagnostics.filter((diagnostic) => diagnostic.severity === "warning").length;
1218
1220
  const affectedFileCount = collectAffectedFiles(diagnostics).size;
@@ -1254,7 +1256,7 @@ const printSummary = (diagnostics, elapsedMilliseconds, scoreResult, projectName
1254
1256
  } else {
1255
1257
  summaryFramedLines.push(createFramedLine("React Doctor (www.react.doctor)", `React Doctor ${highlighter.dim("(www.react.doctor)")}`));
1256
1258
  summaryFramedLines.push(createFramedLine(""));
1257
- summaryFramedLines.push(createFramedLine(OFFLINE_MESSAGE, highlighter.dim(OFFLINE_MESSAGE)));
1259
+ summaryFramedLines.push(createFramedLine(noScoreMessage, highlighter.dim(noScoreMessage)));
1258
1260
  summaryFramedLines.push(createFramedLine(""));
1259
1261
  }
1260
1262
  summaryFramedLines.push(createFramedLine(summaryLinePartsPlain.join(" "), summaryLineParts.join(" ")));
@@ -1279,6 +1281,7 @@ const scan = async (directory, inputOptions = {}) => {
1279
1281
  deadCode: inputOptions.deadCode ?? userConfig?.deadCode ?? true,
1280
1282
  verbose: inputOptions.verbose ?? userConfig?.verbose ?? false,
1281
1283
  scoreOnly: inputOptions.scoreOnly ?? false,
1284
+ offline: inputOptions.offline ?? false,
1282
1285
  includePaths: inputOptions.includePaths
1283
1286
  };
1284
1287
  const includePaths = options.includePaths ?? [];
@@ -1335,10 +1338,11 @@ const scan = async (directory, inputOptions = {}) => {
1335
1338
  ];
1336
1339
  const diagnostics = userConfig ? filterIgnoredDiagnostics(allDiagnostics, userConfig) : allDiagnostics;
1337
1340
  const elapsedMilliseconds = performance.now() - startTime;
1338
- const scoreResult = await calculateScore(diagnostics);
1341
+ const scoreResult = options.offline ? null : await calculateScore(diagnostics);
1342
+ const noScoreMessage = options.offline ? OFFLINE_FLAG_MESSAGE : OFFLINE_MESSAGE;
1339
1343
  if (options.scoreOnly) {
1340
1344
  if (scoreResult) logger.log(`${scoreResult.score}`);
1341
- else logger.dim(OFFLINE_MESSAGE);
1345
+ else logger.dim(noScoreMessage);
1342
1346
  return;
1343
1347
  }
1344
1348
  if (diagnostics.length === 0) {
@@ -1347,12 +1351,12 @@ const scan = async (directory, inputOptions = {}) => {
1347
1351
  if (scoreResult) {
1348
1352
  printBranding(scoreResult.score);
1349
1353
  printScoreGauge(scoreResult.score, scoreResult.label);
1350
- } else logger.dim(` ${OFFLINE_MESSAGE}`);
1354
+ } else logger.dim(` ${noScoreMessage}`);
1351
1355
  return;
1352
1356
  }
1353
1357
  printDiagnostics(diagnostics, options.verbose);
1354
1358
  const displayedSourceFileCount = isDiffMode ? includePaths.length : projectInfo.sourceFileCount;
1355
- printSummary(diagnostics, elapsedMilliseconds, scoreResult, projectInfo.projectName, displayedSourceFileCount);
1359
+ printSummary(diagnostics, elapsedMilliseconds, scoreResult, projectInfo.projectName, displayedSourceFileCount, noScoreMessage);
1356
1360
  };
1357
1361
 
1358
1362
  //#endregion
@@ -1659,7 +1663,7 @@ const maybePromptSkillInstall = async (shouldSkipPrompts) => {
1659
1663
 
1660
1664
  //#endregion
1661
1665
  //#region src/cli.ts
1662
- const VERSION = "0.0.20";
1666
+ const VERSION = "0.0.21";
1663
1667
  process.on("SIGINT", () => process.exit(0));
1664
1668
  process.on("SIGTERM", () => process.exit(0));
1665
1669
  const resolveDiffMode = async (diffInfo, effectiveDiff, shouldSkipPrompts, isScoreOnly) => {
@@ -1684,7 +1688,7 @@ const resolveDiffMode = async (diffInfo, effectiveDiff, shouldSkipPrompts, isSco
1684
1688
  });
1685
1689
  return Boolean(shouldScanBranchOnly);
1686
1690
  };
1687
- const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--no-lint", "skip linting").option("--no-dead-code", "skip dead code detection").option("--verbose", "show file details per rule").option("--score", "output only the score").option("-y, --yes", "skip prompts, scan all workspace projects").option("--project <name>", "select workspace project (comma-separated for multiple)").option("--diff [base]", "scan only files changed vs base branch").option("--fix", "open Ami to auto-fix all issues").option("--prompt", "copy latest scan output to clipboard").action(async (directory, flags) => {
1691
+ const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--no-lint", "skip linting").option("--no-dead-code", "skip dead code detection").option("--verbose", "show file details per rule").option("--score", "output only the score").option("-y, --yes", "skip prompts, scan all workspace projects").option("--project <name>", "select workspace project (comma-separated for multiple)").option("--diff [base]", "scan only files changed vs base branch").option("--offline", "skip telemetry (anonymous, not stored, only used to calculate score)").option("--fix", "open Ami to auto-fix all issues").option("--prompt", "copy latest scan output to clipboard").action(async (directory, flags) => {
1688
1692
  const isScoreOnly = flags.score && !flags.prompt;
1689
1693
  const shouldCopyPromptOutput = flags.prompt;
1690
1694
  if (shouldCopyPromptOutput) startLoggerCapture();
@@ -1700,7 +1704,8 @@ const program = new Command().name("react-doctor").description("Diagnose React c
1700
1704
  lint: isCliOverride("lint") ? flags.lint : userConfig?.lint ?? flags.lint,
1701
1705
  deadCode: isCliOverride("deadCode") ? flags.deadCode : userConfig?.deadCode ?? flags.deadCode,
1702
1706
  verbose: flags.prompt || (isCliOverride("verbose") ? Boolean(flags.verbose) : userConfig?.verbose ?? false),
1703
- scoreOnly: isScoreOnly
1707
+ scoreOnly: isScoreOnly,
1708
+ offline: flags.offline
1704
1709
  };
1705
1710
  const isAutomatedEnvironment = [
1706
1711
  process.env.CI,
@@ -1798,12 +1803,20 @@ const openUrl = (url) => {
1798
1803
  }
1799
1804
  execSync(process.platform === "darwin" ? `open "${url}"` : `xdg-open "${url}"`, { stdio: "ignore" });
1800
1805
  };
1801
- const buildDeeplink = (directory) => {
1802
- return `ami://open-project?cwd=${encodeURIComponent(path.resolve(directory))}&prompt=${encodeURIComponent(DEEPLINK_FIX_PROMPT)}&mode=agent&autoSubmit=true`;
1803
- };
1806
+ const buildDeeplinkParams = (directory) => {
1807
+ const params = new URLSearchParams();
1808
+ params.set("cwd", path.resolve(directory));
1809
+ params.set("prompt", DEEPLINK_FIX_PROMPT);
1810
+ params.set("mode", "agent");
1811
+ params.set("autoSubmit", "true");
1812
+ return params;
1813
+ };
1814
+ const buildDeeplink = (directory) => `ami://open-project?${buildDeeplinkParams(directory).toString()}`;
1815
+ const buildWebDeeplink = (directory) => `${OPEN_BASE_URL}?${buildDeeplinkParams(directory).toString()}`;
1804
1816
  const openAmiToFix = (directory) => {
1805
1817
  const isInstalled = isAmiInstalled();
1806
1818
  const deeplink = buildDeeplink(directory);
1819
+ const webDeeplink = buildWebDeeplink(directory);
1807
1820
  if (!isInstalled) {
1808
1821
  if (process.platform === "darwin") {
1809
1822
  installAmi();
@@ -1814,7 +1827,7 @@ const openAmiToFix = (directory) => {
1814
1827
  }
1815
1828
  logger.break();
1816
1829
  logger.dim("Once Ami is running, open this link to start fixing:");
1817
- logger.info(deeplink);
1830
+ logger.info(webDeeplink);
1818
1831
  return;
1819
1832
  }
1820
1833
  logger.log("Opening Ami to fix react-doctor issues...");
@@ -1824,7 +1837,7 @@ const openAmiToFix = (directory) => {
1824
1837
  } catch {
1825
1838
  logger.break();
1826
1839
  logger.dim("Could not open Ami automatically. Open this URL manually:");
1827
- logger.info(deeplink);
1840
+ logger.info(webDeeplink);
1828
1841
  }
1829
1842
  };
1830
1843
  const buildPromptWithOutput = (reactDoctorOutput) => {