@devicecloud.dev/dcd 5.0.0-beta.0 → 5.0.0-beta.1

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 (101) hide show
  1. package/README.md +35 -0
  2. package/dist/commands/artifacts.d.ts +28 -28
  3. package/dist/commands/artifacts.js +20 -23
  4. package/dist/commands/cloud.d.ts +57 -57
  5. package/dist/commands/cloud.js +173 -186
  6. package/dist/commands/list.d.ts +22 -22
  7. package/dist/commands/list.js +36 -38
  8. package/dist/commands/live.js +134 -127
  9. package/dist/commands/login.d.ts +11 -11
  10. package/dist/commands/login.js +46 -44
  11. package/dist/commands/logout.js +16 -18
  12. package/dist/commands/status.d.ts +11 -11
  13. package/dist/commands/status.js +45 -43
  14. package/dist/commands/switch-org.d.ts +7 -7
  15. package/dist/commands/switch-org.js +19 -21
  16. package/dist/commands/upgrade.js +29 -31
  17. package/dist/commands/upload.d.ts +10 -10
  18. package/dist/commands/upload.js +42 -43
  19. package/dist/commands/whoami.js +17 -20
  20. package/dist/config/environments.js +6 -12
  21. package/dist/config/flags/api.flags.js +1 -4
  22. package/dist/config/flags/binary.flags.js +1 -4
  23. package/dist/config/flags/device.flags.js +6 -9
  24. package/dist/config/flags/environment.flags.js +1 -4
  25. package/dist/config/flags/execution.flags.js +1 -4
  26. package/dist/config/flags/github.flags.js +1 -4
  27. package/dist/config/flags/output.flags.js +1 -4
  28. package/dist/constants.js +15 -18
  29. package/dist/gateways/api-gateway.d.ts +31 -6
  30. package/dist/gateways/api-gateway.js +70 -16
  31. package/dist/gateways/cli-auth-gateway.d.ts +1 -1
  32. package/dist/gateways/cli-auth-gateway.js +3 -6
  33. package/dist/gateways/realtime-gateway.d.ts +32 -0
  34. package/dist/gateways/realtime-gateway.js +103 -0
  35. package/dist/gateways/supabase-gateway.d.ts +1 -1
  36. package/dist/gateways/supabase-gateway.js +10 -14
  37. package/dist/index.js +41 -38
  38. package/dist/mcp/context.d.ts +33 -0
  39. package/dist/mcp/context.js +33 -0
  40. package/dist/mcp/helpers.d.ts +16 -0
  41. package/dist/mcp/helpers.js +34 -0
  42. package/dist/mcp/index.d.ts +2 -0
  43. package/dist/mcp/index.js +24 -0
  44. package/dist/mcp/server.d.ts +7 -0
  45. package/dist/mcp/server.js +27 -0
  46. package/dist/mcp/tools/download-artifacts.d.ts +11 -0
  47. package/dist/mcp/tools/download-artifacts.js +84 -0
  48. package/dist/mcp/tools/get-status.d.ts +7 -0
  49. package/dist/mcp/tools/get-status.js +39 -0
  50. package/dist/mcp/tools/list-devices.d.ts +7 -0
  51. package/dist/mcp/tools/list-devices.js +27 -0
  52. package/dist/mcp/tools/list-runs.d.ts +3 -0
  53. package/dist/mcp/tools/list-runs.js +60 -0
  54. package/dist/mcp/tools/run-cloud-test.d.ts +14 -0
  55. package/dist/mcp/tools/run-cloud-test.js +233 -0
  56. package/dist/methods.d.ts +32 -1
  57. package/dist/methods.js +125 -66
  58. package/dist/services/device-validation.service.d.ts +1 -1
  59. package/dist/services/device-validation.service.js +1 -5
  60. package/dist/services/execution-plan.service.js +14 -17
  61. package/dist/services/execution-plan.utils.js +15 -23
  62. package/dist/services/flow-paths.d.ts +17 -0
  63. package/dist/services/flow-paths.js +52 -0
  64. package/dist/services/metadata-extractor.service.js +22 -25
  65. package/dist/services/moropo.service.js +18 -20
  66. package/dist/services/report-download.service.d.ts +1 -1
  67. package/dist/services/report-download.service.js +5 -9
  68. package/dist/services/results-polling.service.d.ts +18 -3
  69. package/dist/services/results-polling.service.js +195 -108
  70. package/dist/services/telemetry.service.d.ts +10 -1
  71. package/dist/services/telemetry.service.js +40 -18
  72. package/dist/services/test-submission.service.d.ts +21 -4
  73. package/dist/services/test-submission.service.js +51 -34
  74. package/dist/services/version.service.d.ts +1 -1
  75. package/dist/services/version.service.js +1 -5
  76. package/dist/types/domain/auth.types.d.ts +8 -0
  77. package/dist/types/domain/auth.types.js +1 -2
  78. package/dist/types/domain/device.types.js +8 -11
  79. package/dist/types/domain/live.types.js +1 -2
  80. package/dist/types/generated/schema.types.js +1 -2
  81. package/dist/types/index.d.ts +2 -2
  82. package/dist/types/index.js +2 -18
  83. package/dist/types.js +1 -2
  84. package/dist/utils/auth.d.ts +1 -1
  85. package/dist/utils/auth.js +27 -28
  86. package/dist/utils/ci.d.ts +12 -0
  87. package/dist/utils/ci.js +39 -0
  88. package/dist/utils/cli.js +18 -27
  89. package/dist/utils/compatibility.d.ts +1 -1
  90. package/dist/utils/compatibility.js +5 -7
  91. package/dist/utils/config-store.js +33 -43
  92. package/dist/utils/connectivity.js +1 -4
  93. package/dist/utils/expo.js +15 -21
  94. package/dist/utils/orgs.js +8 -12
  95. package/dist/utils/paths.js +2 -5
  96. package/dist/utils/progress.js +2 -5
  97. package/dist/utils/styling.d.ts +35 -37
  98. package/dist/utils/styling.js +52 -86
  99. package/dist/utils/ui.d.ts +41 -0
  100. package/dist/utils/ui.js +95 -0
  101. package/package.json +27 -24
@@ -1,9 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fetchCompatibilityData = fetchCompatibilityData;
4
- exports.clearCompatibilityCache = clearCompatibilityCache;
5
1
  let cachedCompatibilityData = null;
6
- async function fetchCompatibilityData(apiUrl, auth) {
2
+ export async function fetchCompatibilityData(apiUrl, auth) {
7
3
  if (cachedCompatibilityData) {
8
4
  return cachedCompatibilityData;
9
5
  }
@@ -27,9 +23,11 @@ async function fetchCompatibilityData(apiUrl, auth) {
27
23
  }
28
24
  catch (error) {
29
25
  const errorMessage = error instanceof Error ? error.message : String(error);
30
- throw new Error(`Failed to fetch compatibility data from API: ${errorMessage}`);
26
+ throw new Error(`Failed to fetch compatibility data from API: ${errorMessage}`, {
27
+ cause: error,
28
+ });
31
29
  }
32
30
  }
33
- function clearCompatibilityCache() {
31
+ export function clearCompatibilityCache() {
34
32
  cachedCompatibilityData = null;
35
33
  }
@@ -1,13 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CONFIG_SCHEMA_VERSION = void 0;
4
- exports.getConfigDir = getConfigDir;
5
- exports.getConfigPath = getConfigPath;
6
- exports.readConfig = readConfig;
7
- exports.resolveApiUrl = resolveApiUrl;
8
- exports.writeConfig = writeConfig;
9
- exports.clearConfig = clearConfig;
10
- exports.configFileMode = configFileMode;
11
1
  /**
12
2
  * Persistent CLI config: Supabase session tokens + chosen org.
13
3
  *
@@ -16,31 +6,31 @@ exports.configFileMode = configFileMode;
16
6
  * Writes are atomic (tmp file + rename) so a crash mid-refresh can't
17
7
  * leave a corrupt config behind that logs the user out.
18
8
  */
19
- const node_crypto_1 = require("node:crypto");
20
- const node_fs_1 = require("node:fs");
21
- const node_os_1 = require("node:os");
22
- const path = require("node:path");
23
- const environments_1 = require("../config/environments");
24
- exports.CONFIG_SCHEMA_VERSION = 1;
25
- function getConfigDir() {
9
+ import { randomBytes } from 'node:crypto';
10
+ import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync, } from 'node:fs';
11
+ import { homedir } from 'node:os';
12
+ import * as path from 'node:path';
13
+ import { ENVIRONMENTS } from '../config/environments.js';
14
+ export const CONFIG_SCHEMA_VERSION = 1;
15
+ export function getConfigDir() {
26
16
  if (process.env.DCD_CONFIG_DIR)
27
17
  return process.env.DCD_CONFIG_DIR;
28
18
  const xdg = process.env.XDG_CONFIG_HOME;
29
19
  if (xdg && xdg.trim().length > 0)
30
20
  return path.join(xdg, 'dcd');
31
- return path.join((0, node_os_1.homedir)(), '.dcd');
21
+ return path.join(homedir(), '.dcd');
32
22
  }
33
- function getConfigPath() {
23
+ export function getConfigPath() {
34
24
  return path.join(getConfigDir(), 'config.json');
35
25
  }
36
- function readConfig() {
26
+ export function readConfig() {
37
27
  const p = getConfigPath();
38
- if (!(0, node_fs_1.existsSync)(p))
28
+ if (!existsSync(p))
39
29
  return null;
40
30
  try {
41
- const raw = (0, node_fs_1.readFileSync)(p, 'utf8');
31
+ const raw = readFileSync(p, 'utf8');
42
32
  const parsed = JSON.parse(raw);
43
- if (parsed.version !== exports.CONFIG_SCHEMA_VERSION) {
33
+ if (parsed.version !== CONFIG_SCHEMA_VERSION) {
44
34
  // eslint-disable-next-line no-console
45
35
  console.warn(`Warning: config at ${p} was written by an incompatible CLI version (config version ${parsed.version}); ignoring it. Run \`dcd login\` to recreate it.`);
46
36
  return null;
@@ -65,20 +55,20 @@ function readConfig() {
65
55
  * token is rejected with a misleading "Invalid or expired JWT". `switch-org`
66
56
  * has always done this; this helper extends it to every command.
67
57
  */
68
- function resolveApiUrl(flag) {
58
+ export function resolveApiUrl(flag) {
69
59
  const explicit = flag?.trim();
70
60
  if (explicit)
71
61
  return explicit;
72
- return readConfig()?.api_url ?? environments_1.ENVIRONMENTS.prod.apiUrl;
62
+ return readConfig()?.api_url ?? ENVIRONMENTS.prod.apiUrl;
73
63
  }
74
- function writeConfig(config) {
64
+ export function writeConfig(config) {
75
65
  const dir = getConfigDir();
76
- if (!(0, node_fs_1.existsSync)(dir)) {
77
- (0, node_fs_1.mkdirSync)(dir, { recursive: true, mode: 0o700 });
66
+ if (!existsSync(dir)) {
67
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
78
68
  }
79
69
  else {
80
70
  try {
81
- (0, node_fs_1.chmodSync)(dir, 0o700);
71
+ chmodSync(dir, 0o700);
82
72
  }
83
73
  catch { /* best effort */ }
84
74
  }
@@ -88,38 +78,38 @@ function writeConfig(config) {
88
78
  // writeFileSync and renameSync right now.
89
79
  try {
90
80
  const base = path.basename(finalPath);
91
- for (const entry of (0, node_fs_1.readdirSync)(dir)) {
81
+ for (const entry of readdirSync(dir)) {
92
82
  if (!entry.startsWith(`${base}.`) || !entry.endsWith('.tmp'))
93
83
  continue;
94
84
  const tmp = path.join(dir, entry);
95
85
  try {
96
- if (Date.now() - (0, node_fs_1.statSync)(tmp).mtimeMs > 60_000)
97
- (0, node_fs_1.unlinkSync)(tmp);
86
+ if (Date.now() - statSync(tmp).mtimeMs > 60_000)
87
+ unlinkSync(tmp);
98
88
  }
99
89
  catch { /* best effort */ }
100
90
  }
101
91
  }
102
92
  catch { /* best effort */ }
103
- const tmpPath = `${finalPath}.${(0, node_crypto_1.randomBytes)(6).toString('hex')}.tmp`;
104
- (0, node_fs_1.writeFileSync)(tmpPath, JSON.stringify(config, null, 2), { mode: 0o600 });
93
+ const tmpPath = `${finalPath}.${randomBytes(6).toString('hex')}.tmp`;
94
+ writeFileSync(tmpPath, JSON.stringify(config, null, 2), { mode: 0o600 });
105
95
  try {
106
- (0, node_fs_1.chmodSync)(tmpPath, 0o600);
96
+ chmodSync(tmpPath, 0o600);
107
97
  }
108
98
  catch { /* best effort on platforms w/o chmod */ }
109
- (0, node_fs_1.renameSync)(tmpPath, finalPath);
99
+ renameSync(tmpPath, finalPath);
110
100
  try {
111
- (0, node_fs_1.chmodSync)(finalPath, 0o600);
101
+ chmodSync(finalPath, 0o600);
112
102
  }
113
103
  catch { /* best effort */ }
114
104
  }
115
- function clearConfig() {
105
+ export function clearConfig() {
116
106
  const p = getConfigPath();
117
- if ((0, node_fs_1.existsSync)(p))
118
- (0, node_fs_1.unlinkSync)(p);
107
+ if (existsSync(p))
108
+ unlinkSync(p);
119
109
  }
120
- function configFileMode() {
110
+ export function configFileMode() {
121
111
  const p = getConfigPath();
122
- if (!(0, node_fs_1.existsSync)(p))
112
+ if (!existsSync(p))
123
113
  return null;
124
- return (0, node_fs_1.statSync)(p).mode & 0o777;
114
+ return statSync(p).mode & 0o777;
125
115
  }
@@ -1,16 +1,13 @@
1
- "use strict";
2
1
  /**
3
2
  * Utility for checking internet connectivity using third-party endpoints
4
3
  */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.checkInternetConnectivity = checkInternetConnectivity;
7
4
  /**
8
5
  * Check if the system has internet connectivity by testing against
9
6
  * multiple reliable third-party endpoints with detailed diagnostics.
10
7
  *
11
8
  * @returns Promise<ConnectivityCheckResult> - Detailed connectivity check results
12
9
  */
13
- async function checkInternetConnectivity() {
10
+ export async function checkInternetConnectivity() {
14
11
  // Use multiple reliable endpoints to test connectivity
15
12
  const testEndpoints = [
16
13
  { url: 'https://www.google.com/generate_204', description: 'Google' },
@@ -1,17 +1,11 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isUrl = isUrl;
4
- exports.downloadExpoUrl = downloadExpoUrl;
5
- exports.extractTarGz = extractTarGz;
6
- exports.findAppBundle = findAppBundle;
7
- const node_crypto_1 = require("node:crypto");
8
- const fs = require("node:fs");
9
- const fsp = require("node:fs/promises");
10
- const os = require("node:os");
11
- const path = require("node:path");
12
- const node_stream_1 = require("node:stream");
13
- const promises_1 = require("node:stream/promises");
14
- const tar = require("tar");
1
+ import { randomUUID } from 'node:crypto';
2
+ import * as fs from 'node:fs';
3
+ import * as fsp from 'node:fs/promises';
4
+ import * as os from 'node:os';
5
+ import * as path from 'node:path';
6
+ import { Readable } from 'node:stream';
7
+ import { pipeline } from 'node:stream/promises';
8
+ import * as tar from 'tar';
15
9
  const DOWNLOAD_RETRY_ATTEMPTS = 3;
16
10
  const DOWNLOAD_RETRY_DELAY_MS = 2000;
17
11
  /**
@@ -19,7 +13,7 @@ const DOWNLOAD_RETRY_DELAY_MS = 2000;
19
13
  * @param input - String to test
20
14
  * @returns True if the string begins with http:// or https://
21
15
  */
22
- function isUrl(input) {
16
+ export function isUrl(input) {
23
17
  return input.startsWith('http://') || input.startsWith('https://');
24
18
  }
25
19
  /**
@@ -31,8 +25,8 @@ function isUrl(input) {
31
25
  * @param debug - Whether to emit debug log lines
32
26
  * @returns Absolute path to the downloaded temp file
33
27
  */
34
- async function downloadExpoUrl(url, debug) {
35
- const destPath = path.join(os.tmpdir(), `dcd-expo-${(0, node_crypto_1.randomUUID)()}.tar.gz`);
28
+ export async function downloadExpoUrl(url, debug) {
29
+ const destPath = path.join(os.tmpdir(), `dcd-expo-${randomUUID()}.tar.gz`);
36
30
  for (let attempt = 1; attempt <= DOWNLOAD_RETRY_ATTEMPTS; attempt++) {
37
31
  if (debug) {
38
32
  console.log(`[DEBUG] Downloading Expo URL (attempt ${attempt}/${DOWNLOAD_RETRY_ATTEMPTS}): ${url}`);
@@ -60,7 +54,7 @@ async function downloadExpoUrl(url, debug) {
60
54
  }
61
55
  // Stream to disk using pipeline to handle backpressure and avoid loading
62
56
  // the entire archive in memory
63
- await (0, promises_1.pipeline)(node_stream_1.Readable.fromWeb(response.body), fs.createWriteStream(destPath));
57
+ await pipeline(Readable.fromWeb(response.body), fs.createWriteStream(destPath));
64
58
  if (debug) {
65
59
  const stat = await fsp.stat(destPath);
66
60
  console.log(`[DEBUG] Downloaded ${(stat.size / 1024 / 1024).toFixed(2)} MB to ${destPath}`);
@@ -91,8 +85,8 @@ async function downloadExpoUrl(url, debug) {
91
85
  * @param debug - Whether to emit debug log lines
92
86
  * @returns Absolute path to the newly created extract directory
93
87
  */
94
- async function extractTarGz(tarPath, debug) {
95
- const extractDir = path.join(os.tmpdir(), `dcd-expo-${(0, node_crypto_1.randomUUID)()}`);
88
+ export async function extractTarGz(tarPath, debug) {
89
+ const extractDir = path.join(os.tmpdir(), `dcd-expo-${randomUUID()}`);
96
90
  await fsp.mkdir(extractDir, { recursive: true });
97
91
  if (debug) {
98
92
  console.log(`[DEBUG] Extracting ${tarPath} to ${extractDir}`);
@@ -109,7 +103,7 @@ async function extractTarGz(tarPath, debug) {
109
103
  * @param dir - Directory to search within
110
104
  * @returns Absolute path to the .app directory
111
105
  */
112
- async function findAppBundle(dir) {
106
+ export async function findAppBundle(dir) {
113
107
  const candidates = [];
114
108
  async function walk(current, depth) {
115
109
  const entries = await fsp.readdir(current, { withFileTypes: true });
@@ -1,18 +1,14 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fetchOrgs = fetchOrgs;
4
- exports.pickOrg = pickOrg;
5
1
  /**
6
2
  * Shared helpers for fetching and picking from /me/orgs. Used by both
7
3
  * `dcd login` (after the PKCE claim returns a session) and `dcd switch-org`.
8
4
  */
9
- const p = require("@clack/prompts");
10
- const cli_1 = require("./cli");
11
- async function fetchOrgs(apiUrl, headers) {
5
+ import * as p from '@clack/prompts';
6
+ import { CliError } from './cli.js';
7
+ export async function fetchOrgs(apiUrl, headers) {
12
8
  const res = await fetch(`${apiUrl.replace(/\/$/, '')}/me/orgs`, { headers });
13
9
  if (!res.ok) {
14
10
  const body = await res.text().catch(() => '');
15
- throw new cli_1.CliError(`Failed to list organizations: HTTP ${res.status}${body ? ` — ${body}` : ''}`);
11
+ throw new CliError(`Failed to list organizations: HTTP ${res.status}${body ? ` — ${body}` : ''}`);
16
12
  }
17
13
  const body = (await res.json());
18
14
  return body.orgs ?? [];
@@ -21,9 +17,9 @@ async function fetchOrgs(apiUrl, headers) {
21
17
  * Interactive org picker. Auto-selects when there's only one org (returns it
22
18
  * without prompting). Throws on zero orgs or user cancellation.
23
19
  */
24
- async function pickOrg(orgs, message = 'Pick an organization') {
20
+ export async function pickOrg(orgs, message = 'Pick an organization') {
25
21
  if (orgs.length === 0) {
26
- throw new cli_1.CliError('No organizations found for this user.');
22
+ throw new CliError('No organizations found for this user.');
27
23
  }
28
24
  if (orgs.length === 1)
29
25
  return orgs[0];
@@ -32,9 +28,9 @@ async function pickOrg(orgs, message = 'Pick an organization') {
32
28
  options: orgs.map((o) => ({ value: o.id, label: o.name })),
33
29
  });
34
30
  if (p.isCancel(picked))
35
- throw new cli_1.CliError('Cancelled.');
31
+ throw new CliError('Cancelled.');
36
32
  const chosen = orgs.find((o) => o.id === picked);
37
33
  if (!chosen)
38
- throw new cli_1.CliError('No organization selected.');
34
+ throw new CliError('No organization selected.');
39
35
  return chosen;
40
36
  }
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toPortableRelativePath = toPortableRelativePath;
4
- const path = require("node:path");
1
+ import * as path from 'node:path';
5
2
  /**
6
3
  * Convert an absolute path into the portable './'-prefixed, forward-slash
7
4
  * relative form used as flow keys across submission, metadata maps, and
@@ -12,7 +9,7 @@ const path = require("node:path");
12
9
  * Replaces the old `replaceAll(commonRoot, '.')` pattern, which corrupted
13
10
  * paths when the root substring recurred mid-path or collapsed to ''.
14
11
  */
15
- function toPortableRelativePath(absolutePath, commonRoot) {
12
+ export function toPortableRelativePath(absolutePath, commonRoot) {
16
13
  let relative = absolutePath;
17
14
  if (commonRoot && absolutePath.startsWith(commonRoot)) {
18
15
  relative = absolutePath.slice(commonRoot.length);
@@ -1,13 +1,10 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ux = void 0;
4
1
  /**
5
2
  * Progress adapter that wraps @clack/prompts spinner with a
6
3
  * drop-in API for existing services that used oclif's `ux.action` / `ux.info`.
7
4
  *
8
5
  * Keeps call sites unchanged while migrating away from @oclif/core.
9
6
  */
10
- const p = require("@clack/prompts");
7
+ import * as p from '@clack/prompts';
11
8
  class Action {
12
9
  current = null;
13
10
  _status = '';
@@ -41,7 +38,7 @@ class Action {
41
38
  return this._status;
42
39
  }
43
40
  }
44
- exports.ux = {
41
+ export const ux = {
45
42
  action: new Action(),
46
43
  info(message) {
47
44
  // eslint-disable-next-line no-console
@@ -1,4 +1,9 @@
1
- import chalk = require('chalk');
1
+ /**
2
+ * Centralized styling utilities for CLI output
3
+ * Provides consistent, developer-friendly visual formatting
4
+ */
5
+ /** Strip ANSI color escape sequences for visible-width calculations. */
6
+ export declare const stripAnsi: (s: string) => string;
2
7
  /**
3
8
  * Status symbols with associated colors
4
9
  */
@@ -17,50 +22,49 @@ export declare const symbols: {
17
22
  * Color utility functions for semantic styling
18
23
  */
19
24
  export declare const colors: {
20
- readonly bold: chalk.Chalk;
21
- readonly dim: chalk.Chalk;
22
- readonly error: chalk.Chalk;
23
- readonly highlight: chalk.Chalk;
24
- readonly info: chalk.Chalk;
25
- readonly success: chalk.Chalk;
26
- readonly url: chalk.Chalk;
27
- readonly warning: chalk.Chalk;
25
+ readonly bold: import("chalk").ChalkInstance;
26
+ readonly dim: import("chalk").ChalkInstance;
27
+ readonly error: import("chalk").ChalkInstance;
28
+ readonly highlight: import("chalk").ChalkInstance;
29
+ readonly info: import("chalk").ChalkInstance;
30
+ readonly success: import("chalk").ChalkInstance;
31
+ readonly url: import("chalk").ChalkInstance;
32
+ readonly warning: import("chalk").ChalkInstance;
33
+ };
34
+ /**
35
+ * Structural glyphs that give the CLI its tree-shaped layout. `section` marks a
36
+ * top-level heading; `branch` opens the group of detail rows beneath it.
37
+ * See STYLE_GUIDE.md.
38
+ */
39
+ export declare const glyphs: {
40
+ readonly branch: "⎿";
41
+ readonly section: "⏺";
28
42
  };
29
43
  /**
30
- * Dividers for visual separation
44
+ * The single source of truth mapping a run/test status to its colour and
45
+ * (already-coloured) symbol. Both {@link formatStatus} and the `ui` status
46
+ * helpers build on this, so every status reads identically everywhere.
47
+ * @param status - The status string (case-insensitive)
31
48
  */
32
- export declare const dividers: {
33
- readonly heavy: string;
34
- readonly light: string;
35
- readonly short: string;
49
+ export declare function statusPalette(status: string): {
50
+ color: (s: string) => string;
51
+ symbol: string;
36
52
  };
37
53
  /**
38
- * Format a status with appropriate symbol and color
54
+ * Format a status as a coloured symbol followed by the lowercased status word,
55
+ * e.g. `✓ passed`.
39
56
  * @param status - The status string to format
40
57
  * @returns Formatted status string with color and symbol
41
58
  */
42
59
  export declare function formatStatus(status: string): string;
43
60
  /**
44
- * Format a section header
61
+ * Format a top-level section header in the tree style: a `⏺` marker followed by
62
+ * the bold title, preceded by a blank line for separation. Detail rows belong
63
+ * underneath in a branch group (see the `ui` helpers).
45
64
  * @param title - The title of the section
46
65
  * @returns Formatted section header
47
66
  */
48
67
  export declare function sectionHeader(title: string): string;
49
- /**
50
- * Format a key-value pair with optional icon
51
- * @param icon - Icon to display before the key
52
- * @param key - The key name
53
- * @param value - The value to display
54
- * @returns Formatted key-value string
55
- */
56
- export declare function keyValue(icon: string, key: string, value: string): string;
57
- /**
58
- * Format a list item
59
- * @param text - The text of the list item
60
- * @param prefix - The prefix character (default: '•')
61
- * @returns Formatted list item
62
- */
63
- export declare function listItem(text: string, prefix?: string): string;
64
68
  /**
65
69
  * Format a URL
66
70
  * @param url - The URL to format
@@ -87,12 +91,6 @@ export declare function formatTestSummary(summary: {
87
91
  running: number;
88
92
  total: number;
89
93
  }): string;
90
- /**
91
- * Format a box with content
92
- * @param content - The content to display in the box
93
- * @returns Formatted box with borders
94
- */
95
- export declare function box(content: string): string;
96
94
  /**
97
95
  * Minimal column table renderer.
98
96
  * Columns are defined with a `get(row) => string` accessor and optional header label.