@whatalo/cli-kit 1.0.0
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/LICENSE +21 -0
- package/README.md +43 -0
- package/dist/config/index.cjs +250 -0
- package/dist/config/index.d.cts +75 -0
- package/dist/config/index.d.ts +75 -0
- package/dist/config/index.mjs +205 -0
- package/dist/env-file-KvUHlLtI.d.cts +67 -0
- package/dist/env-file-KvUHlLtI.d.ts +67 -0
- package/dist/http/index.cjs +194 -0
- package/dist/http/index.d.cts +56 -0
- package/dist/http/index.d.ts +56 -0
- package/dist/http/index.mjs +166 -0
- package/dist/index.cjs +1055 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.mjs +978 -0
- package/dist/output/index.cjs +276 -0
- package/dist/output/index.d.cts +149 -0
- package/dist/output/index.d.ts +149 -0
- package/dist/output/index.mjs +221 -0
- package/dist/session/index.cjs +184 -0
- package/dist/session/index.d.cts +82 -0
- package/dist/session/index.d.ts +82 -0
- package/dist/session/index.mjs +139 -0
- package/dist/tunnel/index.cjs +252 -0
- package/dist/tunnel/index.d.cts +70 -0
- package/dist/tunnel/index.d.ts +70 -0
- package/dist/tunnel/index.mjs +214 -0
- package/dist/types-DunvRQ0f.d.cts +63 -0
- package/dist/types-DunvRQ0f.d.ts +63 -0
- package/dist/version/index.cjs +204 -0
- package/dist/version/index.d.cts +41 -0
- package/dist/version/index.d.ts +41 -0
- package/dist/version/index.mjs +164 -0
- package/package.json +95 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/output/index.ts
|
|
31
|
+
var output_exports = {};
|
|
32
|
+
__export(output_exports, {
|
|
33
|
+
WhataloAuthError: () => WhataloAuthError,
|
|
34
|
+
WhataloConfigError: () => WhataloConfigError,
|
|
35
|
+
WhataloNetworkError: () => WhataloNetworkError,
|
|
36
|
+
WhataloValidationError: () => WhataloValidationError,
|
|
37
|
+
banner: () => banner,
|
|
38
|
+
code: () => code,
|
|
39
|
+
createSpinner: () => createSpinner,
|
|
40
|
+
error: () => error,
|
|
41
|
+
failMissingNonTTYFlags: () => failMissingNonTTYFlags,
|
|
42
|
+
handleCliError: () => handleCliError,
|
|
43
|
+
info: () => info,
|
|
44
|
+
link: () => link,
|
|
45
|
+
renderInfoPanel: () => renderInfoPanel,
|
|
46
|
+
renderTable: () => renderTable,
|
|
47
|
+
renderTasks: () => renderTasks,
|
|
48
|
+
success: () => success,
|
|
49
|
+
table: () => table,
|
|
50
|
+
warn: () => warn,
|
|
51
|
+
withErrorHandler: () => withErrorHandler
|
|
52
|
+
});
|
|
53
|
+
module.exports = __toCommonJS(output_exports);
|
|
54
|
+
|
|
55
|
+
// src/output/format.ts
|
|
56
|
+
var import_chalk = __toESM(require("chalk"), 1);
|
|
57
|
+
function banner(title, version) {
|
|
58
|
+
console.log();
|
|
59
|
+
console.log(` ${import_chalk.default.bold.cyan(title)} ${import_chalk.default.dim(`v${version}`)}`);
|
|
60
|
+
console.log();
|
|
61
|
+
}
|
|
62
|
+
function success(message) {
|
|
63
|
+
console.log(` ${import_chalk.default.green("\u2713")} ${message}`);
|
|
64
|
+
}
|
|
65
|
+
function error(message) {
|
|
66
|
+
console.log(` ${import_chalk.default.red("\u2717")} ${message}`);
|
|
67
|
+
}
|
|
68
|
+
function warn(message) {
|
|
69
|
+
console.log(` ${import_chalk.default.yellow("\u26A0")} ${message}`);
|
|
70
|
+
}
|
|
71
|
+
function info(message) {
|
|
72
|
+
console.log(` ${import_chalk.default.blue("\u2139")} ${message}`);
|
|
73
|
+
}
|
|
74
|
+
function link(url) {
|
|
75
|
+
return import_chalk.default.underline.cyan(url);
|
|
76
|
+
}
|
|
77
|
+
function code(text) {
|
|
78
|
+
return import_chalk.default.dim("`") + import_chalk.default.bold(text) + import_chalk.default.dim("`");
|
|
79
|
+
}
|
|
80
|
+
function table(headers, rows) {
|
|
81
|
+
if (headers.length === 0) return;
|
|
82
|
+
const widths = headers.map(
|
|
83
|
+
(h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? "").length))
|
|
84
|
+
);
|
|
85
|
+
const headerLine = headers.map((h, i) => h.padEnd(widths[i] ?? h.length)).join(" ");
|
|
86
|
+
console.log(` ${import_chalk.default.bold(headerLine)}`);
|
|
87
|
+
const separator = widths.map((w) => "\u2500".repeat(w)).join(" ");
|
|
88
|
+
console.log(` ${separator}`);
|
|
89
|
+
for (const row of rows) {
|
|
90
|
+
const line = row.map((cell, i) => cell.padEnd(widths[i] ?? cell.length)).join(" ");
|
|
91
|
+
console.log(` ${line}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
var STATUS_ICONS = {
|
|
95
|
+
pending: import_chalk.default.dim("\u25CB"),
|
|
96
|
+
running: import_chalk.default.cyan("\u25C9"),
|
|
97
|
+
success: import_chalk.default.green("\u2713"),
|
|
98
|
+
error: import_chalk.default.red("\u2717"),
|
|
99
|
+
warning: import_chalk.default.yellow("\u26A0"),
|
|
100
|
+
skipped: import_chalk.default.dim("\u2013")
|
|
101
|
+
};
|
|
102
|
+
function renderTasks(tasks) {
|
|
103
|
+
for (const task of tasks) {
|
|
104
|
+
const icon = STATUS_ICONS[task.status];
|
|
105
|
+
const label = task.status === "error" ? import_chalk.default.red(task.label) : task.status === "warning" ? import_chalk.default.yellow(task.label) : task.status === "skipped" ? import_chalk.default.dim(task.label) : task.label;
|
|
106
|
+
console.log(` ${icon} ${label}`);
|
|
107
|
+
if (task.detail) {
|
|
108
|
+
console.log(` ${import_chalk.default.dim(task.detail)}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function renderInfoPanel(title, sections) {
|
|
113
|
+
console.log();
|
|
114
|
+
console.log(` ${import_chalk.default.bold(title)}`);
|
|
115
|
+
console.log(` ${"\u2550".repeat(title.length)}`);
|
|
116
|
+
for (const section of sections) {
|
|
117
|
+
console.log();
|
|
118
|
+
console.log(` ${import_chalk.default.bold.dim(section.heading)}`);
|
|
119
|
+
const maxKeyLen = Math.max(...section.rows.map((r) => r.key.length));
|
|
120
|
+
for (const row of section.rows) {
|
|
121
|
+
console.log(
|
|
122
|
+
` ${import_chalk.default.dim(row.key.padEnd(maxKeyLen))} ${row.value}`
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
console.log();
|
|
127
|
+
}
|
|
128
|
+
function renderTable(options) {
|
|
129
|
+
table(options.headers, options.rows);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/output/spinner.ts
|
|
133
|
+
var import_chalk2 = __toESM(require("chalk"), 1);
|
|
134
|
+
var SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
|
|
135
|
+
var FRAME_INTERVAL_MS = 100;
|
|
136
|
+
function createSpinner(message) {
|
|
137
|
+
let frameIndex = 0;
|
|
138
|
+
let stopped = false;
|
|
139
|
+
const timer = setInterval(() => {
|
|
140
|
+
if (stopped) return;
|
|
141
|
+
const frame = SPINNER_FRAMES[frameIndex % SPINNER_FRAMES.length];
|
|
142
|
+
process.stdout.write(`\x1B[2K\r ${import_chalk2.default.magenta(frame)} ${message}`);
|
|
143
|
+
frameIndex++;
|
|
144
|
+
}, FRAME_INTERVAL_MS);
|
|
145
|
+
const firstFrame = SPINNER_FRAMES[0];
|
|
146
|
+
process.stdout.write(` ${import_chalk2.default.magenta(firstFrame)} ${message}`);
|
|
147
|
+
return {
|
|
148
|
+
stop(finalMessage) {
|
|
149
|
+
if (stopped) return;
|
|
150
|
+
stopped = true;
|
|
151
|
+
clearInterval(timer);
|
|
152
|
+
process.stdout.write(`\x1B[2K\r`);
|
|
153
|
+
if (finalMessage) {
|
|
154
|
+
console.log(` ${import_chalk2.default.green("\u2713")} ${finalMessage}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// src/output/errors.ts
|
|
161
|
+
var WhataloAuthError = class extends Error {
|
|
162
|
+
constructor(message = "Authentication required") {
|
|
163
|
+
super(message);
|
|
164
|
+
this.name = "WhataloAuthError";
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
var WhataloConfigError = class extends Error {
|
|
168
|
+
suggestion;
|
|
169
|
+
constructor(message, suggestion) {
|
|
170
|
+
super(message);
|
|
171
|
+
this.name = "WhataloConfigError";
|
|
172
|
+
this.suggestion = suggestion;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
var WhataloNetworkError = class extends Error {
|
|
176
|
+
statusCode;
|
|
177
|
+
constructor(message, statusCode) {
|
|
178
|
+
super(message);
|
|
179
|
+
this.name = "WhataloNetworkError";
|
|
180
|
+
this.statusCode = statusCode;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
var WhataloValidationError = class extends Error {
|
|
184
|
+
field;
|
|
185
|
+
constructor(message, field) {
|
|
186
|
+
super(message);
|
|
187
|
+
this.name = "WhataloValidationError";
|
|
188
|
+
this.field = field;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// src/output/error-handler.ts
|
|
193
|
+
function withErrorHandler(fn) {
|
|
194
|
+
return async (...args) => {
|
|
195
|
+
try {
|
|
196
|
+
await fn(...args);
|
|
197
|
+
} catch (err) {
|
|
198
|
+
handleCliError(err);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function handleCliError(error2) {
|
|
203
|
+
if (error2 instanceof WhataloAuthError) {
|
|
204
|
+
error(error2.message);
|
|
205
|
+
info("Run `whatalo login` to re-authenticate.");
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
if (error2 instanceof WhataloConfigError) {
|
|
209
|
+
error(error2.message);
|
|
210
|
+
if (error2.suggestion) {
|
|
211
|
+
info(`Fix: ${error2.suggestion}`);
|
|
212
|
+
}
|
|
213
|
+
process.exit(2);
|
|
214
|
+
}
|
|
215
|
+
if (error2 instanceof WhataloNetworkError) {
|
|
216
|
+
error("Could not connect to Whatalo API.");
|
|
217
|
+
if (error2.statusCode === 429) {
|
|
218
|
+
warn("Rate limit reached. Wait a moment and try again.");
|
|
219
|
+
} else {
|
|
220
|
+
info("Check your internet connection and try again.");
|
|
221
|
+
}
|
|
222
|
+
if (error2.message && error2.message !== "Could not connect to Whatalo API.") {
|
|
223
|
+
info(`Details: ${error2.message}`);
|
|
224
|
+
}
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
if (error2 instanceof WhataloValidationError) {
|
|
228
|
+
error(error2.message);
|
|
229
|
+
if (error2.field) {
|
|
230
|
+
info(`Field: ${error2.field}`);
|
|
231
|
+
}
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
error("An unexpected error occurred.");
|
|
235
|
+
if (error2 instanceof Error) {
|
|
236
|
+
info(`Details: ${error2.message}`);
|
|
237
|
+
}
|
|
238
|
+
info(
|
|
239
|
+
"If this persists, run `whatalo info --json` and report the issue."
|
|
240
|
+
);
|
|
241
|
+
process.exit(1);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/output/non-tty.ts
|
|
245
|
+
function failMissingNonTTYFlags(requiredFlags, options) {
|
|
246
|
+
if (process.stdout.isTTY) return;
|
|
247
|
+
const missing = requiredFlags.filter((flag) => !options[flag]);
|
|
248
|
+
if (missing.length > 0) {
|
|
249
|
+
throw new WhataloValidationError(
|
|
250
|
+
`${missing.map((f) => `--${f}`).join(", ")} required in non-interactive environments (CI/CD).`,
|
|
251
|
+
missing[0]
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
256
|
+
0 && (module.exports = {
|
|
257
|
+
WhataloAuthError,
|
|
258
|
+
WhataloConfigError,
|
|
259
|
+
WhataloNetworkError,
|
|
260
|
+
WhataloValidationError,
|
|
261
|
+
banner,
|
|
262
|
+
code,
|
|
263
|
+
createSpinner,
|
|
264
|
+
error,
|
|
265
|
+
failMissingNonTTYFlags,
|
|
266
|
+
handleCliError,
|
|
267
|
+
info,
|
|
268
|
+
link,
|
|
269
|
+
renderInfoPanel,
|
|
270
|
+
renderTable,
|
|
271
|
+
renderTasks,
|
|
272
|
+
success,
|
|
273
|
+
table,
|
|
274
|
+
warn,
|
|
275
|
+
withErrorHandler
|
|
276
|
+
});
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal output formatting helpers.
|
|
3
|
+
* All functions write to stdout. link() and code() return formatted strings
|
|
4
|
+
* so callers can embed them inside larger messages.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Prints a styled banner with the CLI tool name and current version.
|
|
8
|
+
* Adds blank lines above and below for visual separation.
|
|
9
|
+
*/
|
|
10
|
+
declare function banner(title: string, version: string): void;
|
|
11
|
+
/** Prints a green checkmark success message */
|
|
12
|
+
declare function success(message: string): void;
|
|
13
|
+
/** Prints a red cross error message */
|
|
14
|
+
declare function error(message: string): void;
|
|
15
|
+
/** Prints a yellow warning message */
|
|
16
|
+
declare function warn(message: string): void;
|
|
17
|
+
/** Prints a blue informational message */
|
|
18
|
+
declare function info(message: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Returns a styled, underlined URL suitable for terminal hyperlinks.
|
|
21
|
+
* Use inside success(), info(), or console.log() calls.
|
|
22
|
+
*/
|
|
23
|
+
declare function link(url: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Returns an inline monospace-style code fragment.
|
|
26
|
+
* Use inside larger messages: info(`Run ${code("whatalo login")} to start.`)
|
|
27
|
+
*/
|
|
28
|
+
declare function code(text: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Renders a simple text table with a bold header row and separator line.
|
|
31
|
+
* Column widths are computed from the widest value in each column.
|
|
32
|
+
*
|
|
33
|
+
* @param headers - Column header labels
|
|
34
|
+
* @param rows - Data rows; each inner array must align with headers
|
|
35
|
+
*/
|
|
36
|
+
declare function table(headers: string[], rows: string[][]): void;
|
|
37
|
+
type TaskStatus = "pending" | "running" | "success" | "error" | "warning" | "skipped";
|
|
38
|
+
/**
|
|
39
|
+
* Renders a multi-step task list with status indicators.
|
|
40
|
+
* Used by validate, init, and other multi-step commands.
|
|
41
|
+
*/
|
|
42
|
+
declare function renderTasks(tasks: Array<{
|
|
43
|
+
label: string;
|
|
44
|
+
status: TaskStatus;
|
|
45
|
+
detail?: string;
|
|
46
|
+
}>): void;
|
|
47
|
+
/**
|
|
48
|
+
* Renders a key-value info panel with titled sections.
|
|
49
|
+
* Used by `whatalo info` for structured project display.
|
|
50
|
+
*/
|
|
51
|
+
declare function renderInfoPanel(title: string, sections: Array<{
|
|
52
|
+
heading: string;
|
|
53
|
+
rows: Array<{
|
|
54
|
+
key: string;
|
|
55
|
+
value: string;
|
|
56
|
+
}>;
|
|
57
|
+
}>): void;
|
|
58
|
+
/**
|
|
59
|
+
* Renders a table with headers and aligned columns.
|
|
60
|
+
* Truncates cells to fit within maxWidth when specified.
|
|
61
|
+
*/
|
|
62
|
+
declare function renderTable(options: {
|
|
63
|
+
headers: string[];
|
|
64
|
+
rows: string[][];
|
|
65
|
+
maxWidth?: number;
|
|
66
|
+
}): void;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Lightweight terminal spinner using raw ANSI escape codes.
|
|
70
|
+
*
|
|
71
|
+
* Unlike @clack/prompts spinner, this correctly overwrites a single line
|
|
72
|
+
* when used inside long-running polling loops (e.g. Device Flow).
|
|
73
|
+
*/
|
|
74
|
+
interface Spinner {
|
|
75
|
+
/** Stops the spinner and replaces the animated line with a static message */
|
|
76
|
+
stop(finalMessage?: string): void;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Creates and immediately starts an animated terminal spinner.
|
|
80
|
+
*
|
|
81
|
+
* Uses `process.stdout.write` with carriage return (`\r`) and ANSI
|
|
82
|
+
* clear-line (`\x1b[2K`) to overwrite a single line. This avoids the
|
|
83
|
+
* "repeating lines" issue that occurs with @clack/prompts spinner
|
|
84
|
+
* when the event loop yields between frames (e.g. during HTTP polling).
|
|
85
|
+
*
|
|
86
|
+
* @param message - The message to display while the spinner is running
|
|
87
|
+
* @returns A Spinner handle with a stop() method
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* const s = createSpinner("Building plugin...");
|
|
91
|
+
* await runBuild();
|
|
92
|
+
* s.stop("Build complete");
|
|
93
|
+
*/
|
|
94
|
+
declare function createSpinner(message: string): Spinner;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Custom error classes for structured CLI error handling.
|
|
98
|
+
* Each error type maps to a specific recovery action shown to the developer.
|
|
99
|
+
*/
|
|
100
|
+
declare class WhataloAuthError extends Error {
|
|
101
|
+
constructor(message?: string);
|
|
102
|
+
}
|
|
103
|
+
declare class WhataloConfigError extends Error {
|
|
104
|
+
suggestion?: string;
|
|
105
|
+
constructor(message: string, suggestion?: string);
|
|
106
|
+
}
|
|
107
|
+
declare class WhataloNetworkError extends Error {
|
|
108
|
+
statusCode?: number;
|
|
109
|
+
constructor(message: string, statusCode?: number);
|
|
110
|
+
}
|
|
111
|
+
declare class WhataloValidationError extends Error {
|
|
112
|
+
field?: string;
|
|
113
|
+
constructor(message: string, field?: string);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Unified error handler for all CLI commands.
|
|
118
|
+
* Catches any thrown error, formats it with actionable suggestions,
|
|
119
|
+
* and exits with the appropriate code.
|
|
120
|
+
*/
|
|
121
|
+
/**
|
|
122
|
+
* Wraps a CLI command action with structured error handling.
|
|
123
|
+
* Use as the `.action()` callback for Commander commands.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* program.command("validate").action(withErrorHandler(async () => { ... }));
|
|
127
|
+
*/
|
|
128
|
+
declare function withErrorHandler<T extends unknown[]>(fn: (...args: T) => Promise<void>): (...args: T) => Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Formats and displays a CLI error, then exits with the correct code.
|
|
131
|
+
* Exit codes: 1 = recoverable error, 2 = fatal/config error.
|
|
132
|
+
*/
|
|
133
|
+
declare function handleCliError(error: unknown): never;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Non-TTY flag enforcement for CI/CD environments.
|
|
137
|
+
* Prevents silent failures in pipelines by requiring explicit flags
|
|
138
|
+
* for commands that would otherwise need interactive confirmation.
|
|
139
|
+
*/
|
|
140
|
+
/**
|
|
141
|
+
* Fail fast if running in non-TTY and required flags are missing.
|
|
142
|
+
* Used by commands that need confirmation (deploy, env pull).
|
|
143
|
+
*
|
|
144
|
+
* @param requiredFlags - Flag names that must be present in non-TTY
|
|
145
|
+
* @param options - Parsed command options from Commander
|
|
146
|
+
*/
|
|
147
|
+
declare function failMissingNonTTYFlags(requiredFlags: string[], options: Record<string, unknown>): void;
|
|
148
|
+
|
|
149
|
+
export { type Spinner, type TaskStatus, WhataloAuthError, WhataloConfigError, WhataloNetworkError, WhataloValidationError, banner, code, createSpinner, error, failMissingNonTTYFlags, handleCliError, info, link, renderInfoPanel, renderTable, renderTasks, success, table, warn, withErrorHandler };
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal output formatting helpers.
|
|
3
|
+
* All functions write to stdout. link() and code() return formatted strings
|
|
4
|
+
* so callers can embed them inside larger messages.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Prints a styled banner with the CLI tool name and current version.
|
|
8
|
+
* Adds blank lines above and below for visual separation.
|
|
9
|
+
*/
|
|
10
|
+
declare function banner(title: string, version: string): void;
|
|
11
|
+
/** Prints a green checkmark success message */
|
|
12
|
+
declare function success(message: string): void;
|
|
13
|
+
/** Prints a red cross error message */
|
|
14
|
+
declare function error(message: string): void;
|
|
15
|
+
/** Prints a yellow warning message */
|
|
16
|
+
declare function warn(message: string): void;
|
|
17
|
+
/** Prints a blue informational message */
|
|
18
|
+
declare function info(message: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Returns a styled, underlined URL suitable for terminal hyperlinks.
|
|
21
|
+
* Use inside success(), info(), or console.log() calls.
|
|
22
|
+
*/
|
|
23
|
+
declare function link(url: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Returns an inline monospace-style code fragment.
|
|
26
|
+
* Use inside larger messages: info(`Run ${code("whatalo login")} to start.`)
|
|
27
|
+
*/
|
|
28
|
+
declare function code(text: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Renders a simple text table with a bold header row and separator line.
|
|
31
|
+
* Column widths are computed from the widest value in each column.
|
|
32
|
+
*
|
|
33
|
+
* @param headers - Column header labels
|
|
34
|
+
* @param rows - Data rows; each inner array must align with headers
|
|
35
|
+
*/
|
|
36
|
+
declare function table(headers: string[], rows: string[][]): void;
|
|
37
|
+
type TaskStatus = "pending" | "running" | "success" | "error" | "warning" | "skipped";
|
|
38
|
+
/**
|
|
39
|
+
* Renders a multi-step task list with status indicators.
|
|
40
|
+
* Used by validate, init, and other multi-step commands.
|
|
41
|
+
*/
|
|
42
|
+
declare function renderTasks(tasks: Array<{
|
|
43
|
+
label: string;
|
|
44
|
+
status: TaskStatus;
|
|
45
|
+
detail?: string;
|
|
46
|
+
}>): void;
|
|
47
|
+
/**
|
|
48
|
+
* Renders a key-value info panel with titled sections.
|
|
49
|
+
* Used by `whatalo info` for structured project display.
|
|
50
|
+
*/
|
|
51
|
+
declare function renderInfoPanel(title: string, sections: Array<{
|
|
52
|
+
heading: string;
|
|
53
|
+
rows: Array<{
|
|
54
|
+
key: string;
|
|
55
|
+
value: string;
|
|
56
|
+
}>;
|
|
57
|
+
}>): void;
|
|
58
|
+
/**
|
|
59
|
+
* Renders a table with headers and aligned columns.
|
|
60
|
+
* Truncates cells to fit within maxWidth when specified.
|
|
61
|
+
*/
|
|
62
|
+
declare function renderTable(options: {
|
|
63
|
+
headers: string[];
|
|
64
|
+
rows: string[][];
|
|
65
|
+
maxWidth?: number;
|
|
66
|
+
}): void;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Lightweight terminal spinner using raw ANSI escape codes.
|
|
70
|
+
*
|
|
71
|
+
* Unlike @clack/prompts spinner, this correctly overwrites a single line
|
|
72
|
+
* when used inside long-running polling loops (e.g. Device Flow).
|
|
73
|
+
*/
|
|
74
|
+
interface Spinner {
|
|
75
|
+
/** Stops the spinner and replaces the animated line with a static message */
|
|
76
|
+
stop(finalMessage?: string): void;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Creates and immediately starts an animated terminal spinner.
|
|
80
|
+
*
|
|
81
|
+
* Uses `process.stdout.write` with carriage return (`\r`) and ANSI
|
|
82
|
+
* clear-line (`\x1b[2K`) to overwrite a single line. This avoids the
|
|
83
|
+
* "repeating lines" issue that occurs with @clack/prompts spinner
|
|
84
|
+
* when the event loop yields between frames (e.g. during HTTP polling).
|
|
85
|
+
*
|
|
86
|
+
* @param message - The message to display while the spinner is running
|
|
87
|
+
* @returns A Spinner handle with a stop() method
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* const s = createSpinner("Building plugin...");
|
|
91
|
+
* await runBuild();
|
|
92
|
+
* s.stop("Build complete");
|
|
93
|
+
*/
|
|
94
|
+
declare function createSpinner(message: string): Spinner;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Custom error classes for structured CLI error handling.
|
|
98
|
+
* Each error type maps to a specific recovery action shown to the developer.
|
|
99
|
+
*/
|
|
100
|
+
declare class WhataloAuthError extends Error {
|
|
101
|
+
constructor(message?: string);
|
|
102
|
+
}
|
|
103
|
+
declare class WhataloConfigError extends Error {
|
|
104
|
+
suggestion?: string;
|
|
105
|
+
constructor(message: string, suggestion?: string);
|
|
106
|
+
}
|
|
107
|
+
declare class WhataloNetworkError extends Error {
|
|
108
|
+
statusCode?: number;
|
|
109
|
+
constructor(message: string, statusCode?: number);
|
|
110
|
+
}
|
|
111
|
+
declare class WhataloValidationError extends Error {
|
|
112
|
+
field?: string;
|
|
113
|
+
constructor(message: string, field?: string);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Unified error handler for all CLI commands.
|
|
118
|
+
* Catches any thrown error, formats it with actionable suggestions,
|
|
119
|
+
* and exits with the appropriate code.
|
|
120
|
+
*/
|
|
121
|
+
/**
|
|
122
|
+
* Wraps a CLI command action with structured error handling.
|
|
123
|
+
* Use as the `.action()` callback for Commander commands.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* program.command("validate").action(withErrorHandler(async () => { ... }));
|
|
127
|
+
*/
|
|
128
|
+
declare function withErrorHandler<T extends unknown[]>(fn: (...args: T) => Promise<void>): (...args: T) => Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Formats and displays a CLI error, then exits with the correct code.
|
|
131
|
+
* Exit codes: 1 = recoverable error, 2 = fatal/config error.
|
|
132
|
+
*/
|
|
133
|
+
declare function handleCliError(error: unknown): never;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Non-TTY flag enforcement for CI/CD environments.
|
|
137
|
+
* Prevents silent failures in pipelines by requiring explicit flags
|
|
138
|
+
* for commands that would otherwise need interactive confirmation.
|
|
139
|
+
*/
|
|
140
|
+
/**
|
|
141
|
+
* Fail fast if running in non-TTY and required flags are missing.
|
|
142
|
+
* Used by commands that need confirmation (deploy, env pull).
|
|
143
|
+
*
|
|
144
|
+
* @param requiredFlags - Flag names that must be present in non-TTY
|
|
145
|
+
* @param options - Parsed command options from Commander
|
|
146
|
+
*/
|
|
147
|
+
declare function failMissingNonTTYFlags(requiredFlags: string[], options: Record<string, unknown>): void;
|
|
148
|
+
|
|
149
|
+
export { type Spinner, type TaskStatus, WhataloAuthError, WhataloConfigError, WhataloNetworkError, WhataloValidationError, banner, code, createSpinner, error, failMissingNonTTYFlags, handleCliError, info, link, renderInfoPanel, renderTable, renderTasks, success, table, warn, withErrorHandler };
|