@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.
- package/README.md +35 -0
- package/dist/commands/artifacts.d.ts +28 -28
- package/dist/commands/artifacts.js +20 -23
- package/dist/commands/cloud.d.ts +57 -57
- package/dist/commands/cloud.js +173 -186
- package/dist/commands/list.d.ts +22 -22
- package/dist/commands/list.js +36 -38
- package/dist/commands/live.js +134 -127
- package/dist/commands/login.d.ts +11 -11
- package/dist/commands/login.js +46 -44
- package/dist/commands/logout.js +16 -18
- package/dist/commands/status.d.ts +11 -11
- package/dist/commands/status.js +45 -43
- package/dist/commands/switch-org.d.ts +7 -7
- package/dist/commands/switch-org.js +19 -21
- package/dist/commands/upgrade.js +29 -31
- package/dist/commands/upload.d.ts +10 -10
- package/dist/commands/upload.js +42 -43
- package/dist/commands/whoami.js +17 -20
- package/dist/config/environments.js +6 -12
- package/dist/config/flags/api.flags.js +1 -4
- package/dist/config/flags/binary.flags.js +1 -4
- package/dist/config/flags/device.flags.js +6 -9
- package/dist/config/flags/environment.flags.js +1 -4
- package/dist/config/flags/execution.flags.js +1 -4
- package/dist/config/flags/github.flags.js +1 -4
- package/dist/config/flags/output.flags.js +1 -4
- package/dist/constants.js +15 -18
- package/dist/gateways/api-gateway.d.ts +31 -6
- package/dist/gateways/api-gateway.js +70 -16
- package/dist/gateways/cli-auth-gateway.d.ts +1 -1
- package/dist/gateways/cli-auth-gateway.js +3 -6
- package/dist/gateways/realtime-gateway.d.ts +32 -0
- package/dist/gateways/realtime-gateway.js +103 -0
- package/dist/gateways/supabase-gateway.d.ts +1 -1
- package/dist/gateways/supabase-gateway.js +10 -14
- package/dist/index.js +41 -38
- package/dist/mcp/context.d.ts +33 -0
- package/dist/mcp/context.js +33 -0
- package/dist/mcp/helpers.d.ts +16 -0
- package/dist/mcp/helpers.js +34 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +24 -0
- package/dist/mcp/server.d.ts +7 -0
- package/dist/mcp/server.js +27 -0
- package/dist/mcp/tools/download-artifacts.d.ts +11 -0
- package/dist/mcp/tools/download-artifacts.js +84 -0
- package/dist/mcp/tools/get-status.d.ts +7 -0
- package/dist/mcp/tools/get-status.js +39 -0
- package/dist/mcp/tools/list-devices.d.ts +7 -0
- package/dist/mcp/tools/list-devices.js +27 -0
- package/dist/mcp/tools/list-runs.d.ts +3 -0
- package/dist/mcp/tools/list-runs.js +60 -0
- package/dist/mcp/tools/run-cloud-test.d.ts +14 -0
- package/dist/mcp/tools/run-cloud-test.js +233 -0
- package/dist/methods.d.ts +32 -1
- package/dist/methods.js +125 -66
- package/dist/services/device-validation.service.d.ts +1 -1
- package/dist/services/device-validation.service.js +1 -5
- package/dist/services/execution-plan.service.js +14 -17
- package/dist/services/execution-plan.utils.js +15 -23
- package/dist/services/flow-paths.d.ts +17 -0
- package/dist/services/flow-paths.js +52 -0
- package/dist/services/metadata-extractor.service.js +22 -25
- package/dist/services/moropo.service.js +18 -20
- package/dist/services/report-download.service.d.ts +1 -1
- package/dist/services/report-download.service.js +5 -9
- package/dist/services/results-polling.service.d.ts +18 -3
- package/dist/services/results-polling.service.js +195 -108
- package/dist/services/telemetry.service.d.ts +10 -1
- package/dist/services/telemetry.service.js +40 -18
- package/dist/services/test-submission.service.d.ts +21 -4
- package/dist/services/test-submission.service.js +51 -34
- package/dist/services/version.service.d.ts +1 -1
- package/dist/services/version.service.js +1 -5
- package/dist/types/domain/auth.types.d.ts +8 -0
- package/dist/types/domain/auth.types.js +1 -2
- package/dist/types/domain/device.types.js +8 -11
- package/dist/types/domain/live.types.js +1 -2
- package/dist/types/generated/schema.types.js +1 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +2 -18
- package/dist/types.js +1 -2
- package/dist/utils/auth.d.ts +1 -1
- package/dist/utils/auth.js +27 -28
- package/dist/utils/ci.d.ts +12 -0
- package/dist/utils/ci.js +39 -0
- package/dist/utils/cli.js +18 -27
- package/dist/utils/compatibility.d.ts +1 -1
- package/dist/utils/compatibility.js +5 -7
- package/dist/utils/config-store.js +33 -43
- package/dist/utils/connectivity.js +1 -4
- package/dist/utils/expo.js +15 -21
- package/dist/utils/orgs.js +8 -12
- package/dist/utils/paths.js +2 -5
- package/dist/utils/progress.js +2 -5
- package/dist/utils/styling.d.ts +35 -37
- package/dist/utils/styling.js +52 -86
- package/dist/utils/ui.d.ts +41 -0
- package/dist/utils/ui.js +95 -0
- 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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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(
|
|
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 (!
|
|
28
|
+
if (!existsSync(p))
|
|
39
29
|
return null;
|
|
40
30
|
try {
|
|
41
|
-
const raw =
|
|
31
|
+
const raw = readFileSync(p, 'utf8');
|
|
42
32
|
const parsed = JSON.parse(raw);
|
|
43
|
-
if (parsed.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 ??
|
|
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 (!
|
|
77
|
-
|
|
66
|
+
if (!existsSync(dir)) {
|
|
67
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
78
68
|
}
|
|
79
69
|
else {
|
|
80
70
|
try {
|
|
81
|
-
|
|
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
|
|
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() -
|
|
97
|
-
|
|
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}.${
|
|
104
|
-
|
|
93
|
+
const tmpPath = `${finalPath}.${randomBytes(6).toString('hex')}.tmp`;
|
|
94
|
+
writeFileSync(tmpPath, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
105
95
|
try {
|
|
106
|
-
|
|
96
|
+
chmodSync(tmpPath, 0o600);
|
|
107
97
|
}
|
|
108
98
|
catch { /* best effort on platforms w/o chmod */ }
|
|
109
|
-
|
|
99
|
+
renameSync(tmpPath, finalPath);
|
|
110
100
|
try {
|
|
111
|
-
|
|
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 (
|
|
118
|
-
|
|
107
|
+
if (existsSync(p))
|
|
108
|
+
unlinkSync(p);
|
|
119
109
|
}
|
|
120
|
-
function configFileMode() {
|
|
110
|
+
export function configFileMode() {
|
|
121
111
|
const p = getConfigPath();
|
|
122
|
-
if (!
|
|
112
|
+
if (!existsSync(p))
|
|
123
113
|
return null;
|
|
124
|
-
return
|
|
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' },
|
package/dist/utils/expo.js
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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-${
|
|
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
|
|
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-${
|
|
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 });
|
package/dist/utils/orgs.js
CHANGED
|
@@ -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
|
-
|
|
10
|
-
|
|
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
|
|
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
|
|
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
|
|
31
|
+
throw new CliError('Cancelled.');
|
|
36
32
|
const chosen = orgs.find((o) => o.id === picked);
|
|
37
33
|
if (!chosen)
|
|
38
|
-
throw new
|
|
34
|
+
throw new CliError('No organization selected.');
|
|
39
35
|
return chosen;
|
|
40
36
|
}
|
package/dist/utils/paths.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
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);
|
package/dist/utils/progress.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
41
|
+
export const ux = {
|
|
45
42
|
action: new Action(),
|
|
46
43
|
info(message) {
|
|
47
44
|
// eslint-disable-next-line no-console
|
package/dist/utils/styling.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
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.
|
|
21
|
-
readonly dim: chalk.
|
|
22
|
-
readonly error: chalk.
|
|
23
|
-
readonly highlight: chalk.
|
|
24
|
-
readonly info: chalk.
|
|
25
|
-
readonly success: chalk.
|
|
26
|
-
readonly url: chalk.
|
|
27
|
-
readonly warning: 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
|
-
*
|
|
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
|
|
33
|
-
|
|
34
|
-
|
|
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
|
|
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.
|