@yoqa/cli 0.3.12 → 0.3.13

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.
Files changed (2) hide show
  1. package/dist/main.js +125 -19
  2. package/package.json +2 -2
package/dist/main.js CHANGED
@@ -7850,7 +7850,7 @@ var {
7850
7850
  // package.json
7851
7851
  var package_default = {
7852
7852
  name: "@yoqa/cli",
7853
- version: "0.3.12",
7853
+ version: "0.3.13",
7854
7854
  description: "Yoqa CLI — drive local mobile QA from the terminal or CI (talks to the Yoqa runner over HTTP)",
7855
7855
  license: "UNLICENSED",
7856
7856
  type: "module",
@@ -7888,7 +7888,7 @@ var package_default = {
7888
7888
  health: "bun run src/main.ts health"
7889
7889
  },
7890
7890
  dependencies: {
7891
- "@yoqa/runner": "0.3.12"
7891
+ "@yoqa/runner": "0.3.13"
7892
7892
  },
7893
7893
  devDependencies: {
7894
7894
  "@types/node": "^22.15.30",
@@ -7902,6 +7902,127 @@ var package_default = {
7902
7902
  }
7903
7903
  };
7904
7904
 
7905
+ // src/doctor-table.ts
7906
+ var ANSI = {
7907
+ reset: "\x1B[0m",
7908
+ bold: "\x1B[1m",
7909
+ dim: "\x1B[2m",
7910
+ green: "\x1B[32m",
7911
+ red: "\x1B[31m",
7912
+ yellow: "\x1B[33m"
7913
+ };
7914
+ var CHECK_STATUS_LABEL = {
7915
+ pass: "PASS",
7916
+ fail: "FAIL",
7917
+ warn: "WARN"
7918
+ };
7919
+ var STEP_SEVERITY_LABEL = {
7920
+ error: "ERROR",
7921
+ warn: "WARN",
7922
+ info: "INFO"
7923
+ };
7924
+ function doctorColorEnabled(env = process.env, isTty = Boolean(process.stdout.isTTY)) {
7925
+ if (env.NO_COLOR != null && env.NO_COLOR !== "")
7926
+ return false;
7927
+ if (env.FORCE_COLOR != null && env.FORCE_COLOR !== "" && env.FORCE_COLOR !== "0")
7928
+ return true;
7929
+ return isTty;
7930
+ }
7931
+ function paint(text, color, enabled) {
7932
+ if (!enabled)
7933
+ return text;
7934
+ if (color === "dim")
7935
+ return `${ANSI.dim}${text}${ANSI.reset}`;
7936
+ if (color === "bold")
7937
+ return `${ANSI.bold}${text}${ANSI.reset}`;
7938
+ return `${ANSI.bold}${ANSI[color]}${text}${ANSI.reset}`;
7939
+ }
7940
+ function checkColor(status) {
7941
+ if (status === "pass")
7942
+ return "green";
7943
+ if (status === "fail")
7944
+ return "red";
7945
+ return "yellow";
7946
+ }
7947
+ function stepColor(severity) {
7948
+ if (severity === "error")
7949
+ return "red";
7950
+ if (severity === "warn")
7951
+ return "yellow";
7952
+ return "green";
7953
+ }
7954
+ var ESC = "\x1B";
7955
+ function stripAnsi(text) {
7956
+ let out = "";
7957
+ for (let i = 0;i < text.length; i++) {
7958
+ if (text[i] === ESC && text[i + 1] === "[") {
7959
+ const end = text.indexOf("m", i + 2);
7960
+ if (end !== -1) {
7961
+ i = end;
7962
+ continue;
7963
+ }
7964
+ }
7965
+ out += text[i];
7966
+ }
7967
+ return out;
7968
+ }
7969
+ function visibleWidth(text) {
7970
+ return stripAnsi(text).length;
7971
+ }
7972
+ function padEndVisible(text, width) {
7973
+ const extra = width - visibleWidth(text);
7974
+ return extra > 0 ? `${text}${" ".repeat(extra)}` : text;
7975
+ }
7976
+ function cell(value) {
7977
+ const text = value?.replace(/\s+/g, " ").trim() ?? "";
7978
+ return text.length > 0 ? text : "—";
7979
+ }
7980
+ function columnWidths(headers, rows) {
7981
+ return headers.map((header, index) => {
7982
+ let width = header.length;
7983
+ for (const row of rows) {
7984
+ const value = row[index] ?? "";
7985
+ width = Math.max(width, visibleWidth(value));
7986
+ }
7987
+ return width;
7988
+ });
7989
+ }
7990
+ function formatTable(headers, rows, color) {
7991
+ const widths = columnWidths(headers, rows);
7992
+ const headerLine = headers.map((header, index) => padEndVisible(paint(header, "dim", color), widths[index] ?? header.length)).join(" ");
7993
+ const rule = widths.map((width) => "─".repeat(width)).join(" ");
7994
+ const body = rows.map((row) => row.map((value, index) => padEndVisible(value, widths[index] ?? visibleWidth(value))).join(" "));
7995
+ return [headerLine, paint(rule, "dim", color), ...body].join(`
7996
+ `);
7997
+ }
7998
+ function checkDetail(check) {
7999
+ const parts = [check.detail, check.status !== "pass" ? check.fixHint : undefined].filter((part) => Boolean(part));
8000
+ return cell(parts.join(" · "));
8001
+ }
8002
+ function formatDoctorReport(report, color = doctorColorEnabled()) {
8003
+ const lines = [];
8004
+ const summary = report.ok ? "doctor ok" : "doctor issues found";
8005
+ lines.push(paint(summary, report.ok ? "green" : "red", color));
8006
+ lines.push("");
8007
+ if (report.checks.length > 0) {
8008
+ const rows = report.checks.map((check) => {
8009
+ const status = paint(CHECK_STATUS_LABEL[check.status], checkColor(check.status), color);
8010
+ return [status, check.label, checkDetail(check)];
8011
+ });
8012
+ lines.push(formatTable(["STATUS", "CHECK", "DETAIL"], rows, color));
8013
+ }
8014
+ if (report.steps.length > 0) {
8015
+ lines.push("");
8016
+ const rows = report.steps.map((step) => {
8017
+ const severity = paint(STEP_SEVERITY_LABEL[step.severity], stepColor(step.severity), color);
8018
+ return [severity, step.title, cell(step.detail)];
8019
+ });
8020
+ lines.push(formatTable(["SEV", "STEP", "DETAIL"], rows, color));
8021
+ }
8022
+ return lines.join(`
8023
+ `);
8024
+ }
8025
+
7905
8026
  // src/ensure-runner.ts
7906
8027
  import { spawn } from "node:child_process";
7907
8028
  import { existsSync } from "node:fs";
@@ -8742,13 +8863,7 @@ program2.command("doctor").description("Diagnose local tooling, drivers, and lef
8742
8863
  console.log(JSON.stringify(result, null, 2));
8743
8864
  } else {
8744
8865
  console.log(result.message);
8745
- console.log(result.report.ok ? "doctor: ok" : "doctor: issues remain");
8746
- for (const check of result.report.checks) {
8747
- console.log(` [${check.status}] ${check.label}${check.detail ? ` — ${check.detail}` : ""}`);
8748
- }
8749
- for (const step of result.report.steps) {
8750
- console.log(` → [${step.severity}] ${step.title}: ${step.detail}`);
8751
- }
8866
+ console.log(formatDoctorReport(result.report));
8752
8867
  }
8753
8868
  if (!result.report.ok)
8754
8869
  process.exitCode = 1;
@@ -8758,16 +8873,7 @@ program2.command("doctor").description("Diagnose local tooling, drivers, and lef
8758
8873
  if (options.json) {
8759
8874
  console.log(JSON.stringify(report, null, 2));
8760
8875
  } else {
8761
- console.log(report.ok ? "doctor: ok" : "doctor: issues found");
8762
- for (const check of report.checks) {
8763
- console.log(` [${check.status}] ${check.label}${check.detail ? ` — ${check.detail}` : ""}`);
8764
- }
8765
- if (report.steps.length > 0) {
8766
- console.log("steps:");
8767
- for (const step of report.steps) {
8768
- console.log(` → [${step.severity}] ${step.title}: ${step.detail}`);
8769
- }
8770
- }
8876
+ console.log(formatDoctorReport(report));
8771
8877
  }
8772
8878
  if (!report.ok)
8773
8879
  process.exitCode = 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yoqa/cli",
3
- "version": "0.3.12",
3
+ "version": "0.3.13",
4
4
  "description": "Yoqa CLI — drive local mobile QA from the terminal or CI (talks to the Yoqa runner over HTTP)",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -38,7 +38,7 @@
38
38
  "health": "bun run src/main.ts health"
39
39
  },
40
40
  "dependencies": {
41
- "@yoqa/runner": "0.3.12"
41
+ "@yoqa/runner": "0.3.13"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^22.15.30",