@robinmordasiewicz/f5xc-xcsh 6.37.0 → 6.38.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/completions/_xcsh +2 -0
- package/completions/xcsh.bash +2 -2
- package/completions/xcsh.fish +2 -0
- package/dist/index.js +908 -255
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45354,8 +45354,8 @@ function getLogoModeFromEnv(envPrefix) {
|
|
|
45354
45354
|
var CLI_NAME = "xcsh";
|
|
45355
45355
|
var CLI_FULL_NAME = "F5 Distributed Cloud Shell";
|
|
45356
45356
|
function getVersion() {
|
|
45357
|
-
if ("6.
|
|
45358
|
-
return "6.
|
|
45357
|
+
if ("6.38.0") {
|
|
45358
|
+
return "6.38.0";
|
|
45359
45359
|
}
|
|
45360
45360
|
if (process.env.XCSH_VERSION) {
|
|
45361
45361
|
return process.env.XCSH_VERSION;
|
|
@@ -46024,6 +46024,728 @@ var APIClient = class {
|
|
|
46024
46024
|
}
|
|
46025
46025
|
};
|
|
46026
46026
|
|
|
46027
|
+
// src/output/formatter.ts
|
|
46028
|
+
var import_yaml2 = __toESM(require_dist(), 1);
|
|
46029
|
+
|
|
46030
|
+
// src/output/types.ts
|
|
46031
|
+
var DEFAULT_TABLE_STYLE = {
|
|
46032
|
+
unicode: true,
|
|
46033
|
+
coloredBorders: true,
|
|
46034
|
+
headerStyle: "bold"
|
|
46035
|
+
};
|
|
46036
|
+
var PLAIN_TABLE_STYLE = {
|
|
46037
|
+
unicode: false,
|
|
46038
|
+
coloredBorders: false,
|
|
46039
|
+
headerStyle: "normal"
|
|
46040
|
+
};
|
|
46041
|
+
function isValidOutputFormat(format) {
|
|
46042
|
+
return ["json", "yaml", "table", "text", "tsv", "none", "spec"].includes(
|
|
46043
|
+
format.toLowerCase()
|
|
46044
|
+
);
|
|
46045
|
+
}
|
|
46046
|
+
|
|
46047
|
+
// src/output/resolver.ts
|
|
46048
|
+
var OUTPUT_FORMAT_ENV_VAR = `${ENV_PREFIX}_OUTPUT_FORMAT`;
|
|
46049
|
+
function getOutputFormatFromEnv() {
|
|
46050
|
+
const envValue = process.env[OUTPUT_FORMAT_ENV_VAR]?.toLowerCase().trim();
|
|
46051
|
+
if (envValue && isValidOutputFormat(envValue)) {
|
|
46052
|
+
return envValue;
|
|
46053
|
+
}
|
|
46054
|
+
return void 0;
|
|
46055
|
+
}
|
|
46056
|
+
function shouldUseColors(isTTY = process.stdout.isTTY ?? false, noColorFlag = false) {
|
|
46057
|
+
if (noColorFlag) {
|
|
46058
|
+
return false;
|
|
46059
|
+
}
|
|
46060
|
+
if (process.env.NO_COLOR !== void 0) {
|
|
46061
|
+
return false;
|
|
46062
|
+
}
|
|
46063
|
+
if (process.env.FORCE_COLOR !== void 0) {
|
|
46064
|
+
return true;
|
|
46065
|
+
}
|
|
46066
|
+
return isTTY;
|
|
46067
|
+
}
|
|
46068
|
+
|
|
46069
|
+
// src/output/table.ts
|
|
46070
|
+
var UNICODE_BOX = {
|
|
46071
|
+
topLeft: "\u256D",
|
|
46072
|
+
// ╭
|
|
46073
|
+
topRight: "\u256E",
|
|
46074
|
+
// ╮
|
|
46075
|
+
bottomLeft: "\u2570",
|
|
46076
|
+
// ╰
|
|
46077
|
+
bottomRight: "\u256F",
|
|
46078
|
+
// ╯
|
|
46079
|
+
horizontal: "\u2500",
|
|
46080
|
+
// ─
|
|
46081
|
+
vertical: "\u2502",
|
|
46082
|
+
// │
|
|
46083
|
+
leftT: "\u251C",
|
|
46084
|
+
// ├
|
|
46085
|
+
rightT: "\u2524",
|
|
46086
|
+
// ┤
|
|
46087
|
+
topT: "\u252C",
|
|
46088
|
+
// ┬
|
|
46089
|
+
bottomT: "\u2534",
|
|
46090
|
+
// ┴
|
|
46091
|
+
cross: "\u253C"
|
|
46092
|
+
// ┼
|
|
46093
|
+
};
|
|
46094
|
+
var ASCII_BOX = {
|
|
46095
|
+
topLeft: "+",
|
|
46096
|
+
topRight: "+",
|
|
46097
|
+
bottomLeft: "+",
|
|
46098
|
+
bottomRight: "+",
|
|
46099
|
+
horizontal: "-",
|
|
46100
|
+
vertical: "|",
|
|
46101
|
+
leftT: "+",
|
|
46102
|
+
rightT: "+",
|
|
46103
|
+
topT: "+",
|
|
46104
|
+
bottomT: "+",
|
|
46105
|
+
cross: "+"
|
|
46106
|
+
};
|
|
46107
|
+
function getBoxCharacters(style) {
|
|
46108
|
+
return style.unicode ? UNICODE_BOX : ASCII_BOX;
|
|
46109
|
+
}
|
|
46110
|
+
function applyColor(text, color, useColors) {
|
|
46111
|
+
if (!useColors) {
|
|
46112
|
+
return text;
|
|
46113
|
+
}
|
|
46114
|
+
return `${color}${text}${colors.reset}`;
|
|
46115
|
+
}
|
|
46116
|
+
function wrapText2(text, maxWidth) {
|
|
46117
|
+
if (text.length <= maxWidth) {
|
|
46118
|
+
return [text];
|
|
46119
|
+
}
|
|
46120
|
+
const lines = [];
|
|
46121
|
+
let remaining = text;
|
|
46122
|
+
while (remaining.length > 0) {
|
|
46123
|
+
if (remaining.length <= maxWidth) {
|
|
46124
|
+
lines.push(remaining);
|
|
46125
|
+
break;
|
|
46126
|
+
}
|
|
46127
|
+
let breakPoint = maxWidth;
|
|
46128
|
+
for (let i = maxWidth - 1; i > 0; i--) {
|
|
46129
|
+
if (remaining[i] === " ") {
|
|
46130
|
+
breakPoint = i;
|
|
46131
|
+
break;
|
|
46132
|
+
}
|
|
46133
|
+
}
|
|
46134
|
+
lines.push(remaining.slice(0, breakPoint));
|
|
46135
|
+
remaining = remaining.slice(breakPoint).trimStart();
|
|
46136
|
+
}
|
|
46137
|
+
return lines;
|
|
46138
|
+
}
|
|
46139
|
+
function getValue(row, accessor) {
|
|
46140
|
+
if (typeof accessor === "function") {
|
|
46141
|
+
return accessor(row);
|
|
46142
|
+
}
|
|
46143
|
+
const value = row[accessor];
|
|
46144
|
+
if (value === null || value === void 0) {
|
|
46145
|
+
return "";
|
|
46146
|
+
}
|
|
46147
|
+
if (typeof value === "object") {
|
|
46148
|
+
if (accessor === "labels") {
|
|
46149
|
+
return formatLabelsValue(value);
|
|
46150
|
+
}
|
|
46151
|
+
return JSON.stringify(value);
|
|
46152
|
+
}
|
|
46153
|
+
return String(value);
|
|
46154
|
+
}
|
|
46155
|
+
function formatLabelsValue(labels) {
|
|
46156
|
+
const entries = Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}:${v}`);
|
|
46157
|
+
if (entries.length === 0) {
|
|
46158
|
+
return "";
|
|
46159
|
+
}
|
|
46160
|
+
return `map[${entries.join(" ")}]`;
|
|
46161
|
+
}
|
|
46162
|
+
function calculateColumnWidths(columns, rows, maxTableWidth) {
|
|
46163
|
+
const widths = columns.map((col) => {
|
|
46164
|
+
let width = col.header.length;
|
|
46165
|
+
for (const row of rows) {
|
|
46166
|
+
const value = getValue(row, col.accessor);
|
|
46167
|
+
width = Math.max(width, value.length);
|
|
46168
|
+
}
|
|
46169
|
+
if (col.minWidth) {
|
|
46170
|
+
width = Math.max(width, col.minWidth);
|
|
46171
|
+
}
|
|
46172
|
+
if (col.maxWidth) {
|
|
46173
|
+
width = Math.min(width, col.maxWidth);
|
|
46174
|
+
}
|
|
46175
|
+
if (col.width) {
|
|
46176
|
+
width = col.width;
|
|
46177
|
+
}
|
|
46178
|
+
return width;
|
|
46179
|
+
});
|
|
46180
|
+
if (maxTableWidth) {
|
|
46181
|
+
const totalWidth = widths.reduce((a, b) => a + b, 0) + columns.length * 3 + 1;
|
|
46182
|
+
if (totalWidth > maxTableWidth) {
|
|
46183
|
+
const ratio = (maxTableWidth - columns.length * 3 - 1) / totalWidth;
|
|
46184
|
+
for (let i = 0; i < widths.length; i++) {
|
|
46185
|
+
widths[i] = Math.max(5, Math.floor(widths[i] * ratio));
|
|
46186
|
+
}
|
|
46187
|
+
}
|
|
46188
|
+
}
|
|
46189
|
+
return widths;
|
|
46190
|
+
}
|
|
46191
|
+
function formatBeautifulTable(data, config, noColor = false) {
|
|
46192
|
+
if (data.length === 0) {
|
|
46193
|
+
return "";
|
|
46194
|
+
}
|
|
46195
|
+
const useColors = shouldUseColors(void 0, noColor);
|
|
46196
|
+
const style = useColors ? config.style ?? DEFAULT_TABLE_STYLE : PLAIN_TABLE_STYLE;
|
|
46197
|
+
const box = getBoxCharacters(style);
|
|
46198
|
+
const borderColor = style.borderColor ?? colors.red;
|
|
46199
|
+
const widths = calculateColumnWidths(config.columns, data, config.maxWidth);
|
|
46200
|
+
const lines = [];
|
|
46201
|
+
const colorBorder = (text) => applyColor(text, borderColor, useColors && style.coloredBorders);
|
|
46202
|
+
const buildHorizontalLine = (left, mid, right, fill) => {
|
|
46203
|
+
const segments = widths.map((w) => fill.repeat(w + 2));
|
|
46204
|
+
return colorBorder(left + segments.join(mid) + right);
|
|
46205
|
+
};
|
|
46206
|
+
if (config.title) {
|
|
46207
|
+
const title = ` ${config.title} `;
|
|
46208
|
+
const totalWidth = widths.reduce((a, b) => a + b, 0) + widths.length * 3 - 1;
|
|
46209
|
+
const remainingWidth = totalWidth - title.length;
|
|
46210
|
+
const leftDashes = 1;
|
|
46211
|
+
const rightDashes = Math.max(0, remainingWidth - leftDashes);
|
|
46212
|
+
lines.push(
|
|
46213
|
+
colorBorder(box.topLeft + box.horizontal.repeat(leftDashes)) + title + colorBorder(box.horizontal.repeat(rightDashes) + box.topRight)
|
|
46214
|
+
);
|
|
46215
|
+
} else {
|
|
46216
|
+
lines.push(
|
|
46217
|
+
buildHorizontalLine(
|
|
46218
|
+
box.topLeft,
|
|
46219
|
+
box.topT,
|
|
46220
|
+
box.topRight,
|
|
46221
|
+
box.horizontal
|
|
46222
|
+
)
|
|
46223
|
+
);
|
|
46224
|
+
}
|
|
46225
|
+
const headerCells = config.columns.map((col, i) => {
|
|
46226
|
+
const padding = widths[i] - col.header.length;
|
|
46227
|
+
const leftPad = Math.floor(padding / 2);
|
|
46228
|
+
const rightPad = padding - leftPad;
|
|
46229
|
+
const content = " ".repeat(leftPad) + col.header + " ".repeat(rightPad);
|
|
46230
|
+
return ` ${content} `;
|
|
46231
|
+
});
|
|
46232
|
+
lines.push(
|
|
46233
|
+
colorBorder(box.vertical) + headerCells.join(colorBorder(box.vertical)) + colorBorder(box.vertical)
|
|
46234
|
+
);
|
|
46235
|
+
lines.push(
|
|
46236
|
+
buildHorizontalLine(box.leftT, box.cross, box.rightT, box.horizontal)
|
|
46237
|
+
);
|
|
46238
|
+
for (let rowIndex = 0; rowIndex < data.length; rowIndex++) {
|
|
46239
|
+
const row = data[rowIndex];
|
|
46240
|
+
const cellValues = config.columns.map((col, i) => {
|
|
46241
|
+
const value = getValue(row, col.accessor) || "<None>";
|
|
46242
|
+
return config.wrapText !== false ? wrapText2(value, widths[i]) : [value.slice(0, widths[i])];
|
|
46243
|
+
});
|
|
46244
|
+
const maxLines = Math.max(...cellValues.map((c) => c.length));
|
|
46245
|
+
for (let lineIndex = 0; lineIndex < maxLines; lineIndex++) {
|
|
46246
|
+
const cells = cellValues.map((cellLines, i) => {
|
|
46247
|
+
const text = cellLines[lineIndex] ?? "";
|
|
46248
|
+
const padding = widths[i] - text.length;
|
|
46249
|
+
const align = config.columns[i]?.align ?? "left";
|
|
46250
|
+
let content;
|
|
46251
|
+
if (align === "center") {
|
|
46252
|
+
const leftPad = Math.floor(padding / 2);
|
|
46253
|
+
const rightPad = padding - leftPad;
|
|
46254
|
+
content = " ".repeat(leftPad) + text + " ".repeat(rightPad);
|
|
46255
|
+
} else if (align === "right") {
|
|
46256
|
+
content = " ".repeat(padding) + text;
|
|
46257
|
+
} else {
|
|
46258
|
+
content = text + " ".repeat(padding);
|
|
46259
|
+
}
|
|
46260
|
+
return ` ${content} `;
|
|
46261
|
+
});
|
|
46262
|
+
lines.push(
|
|
46263
|
+
colorBorder(box.vertical) + cells.join(colorBorder(box.vertical)) + colorBorder(box.vertical)
|
|
46264
|
+
);
|
|
46265
|
+
}
|
|
46266
|
+
if (rowIndex < data.length - 1 && config.rowSeparators) {
|
|
46267
|
+
lines.push(
|
|
46268
|
+
buildHorizontalLine(
|
|
46269
|
+
box.leftT,
|
|
46270
|
+
box.cross,
|
|
46271
|
+
box.rightT,
|
|
46272
|
+
box.horizontal
|
|
46273
|
+
)
|
|
46274
|
+
);
|
|
46275
|
+
}
|
|
46276
|
+
}
|
|
46277
|
+
lines.push(
|
|
46278
|
+
buildHorizontalLine(
|
|
46279
|
+
box.bottomLeft,
|
|
46280
|
+
box.bottomT,
|
|
46281
|
+
box.bottomRight,
|
|
46282
|
+
box.horizontal
|
|
46283
|
+
)
|
|
46284
|
+
);
|
|
46285
|
+
return lines.join("\n");
|
|
46286
|
+
}
|
|
46287
|
+
var DEFAULT_RESOURCE_COLUMNS = [
|
|
46288
|
+
{ header: "NAMESPACE", accessor: "namespace", minWidth: 9 },
|
|
46289
|
+
{ header: "NAME", accessor: "name", minWidth: 10, maxWidth: 40 },
|
|
46290
|
+
{ header: "LABELS", accessor: "labels", minWidth: 10, maxWidth: 35 }
|
|
46291
|
+
];
|
|
46292
|
+
function formatResourceTable(data, noColor = false) {
|
|
46293
|
+
const items = extractItems(data);
|
|
46294
|
+
if (items.length === 0) {
|
|
46295
|
+
return "";
|
|
46296
|
+
}
|
|
46297
|
+
return formatBeautifulTable(
|
|
46298
|
+
items,
|
|
46299
|
+
{
|
|
46300
|
+
columns: DEFAULT_RESOURCE_COLUMNS,
|
|
46301
|
+
wrapText: true
|
|
46302
|
+
},
|
|
46303
|
+
noColor
|
|
46304
|
+
);
|
|
46305
|
+
}
|
|
46306
|
+
function extractItems(data) {
|
|
46307
|
+
if (data && typeof data === "object" && "items" in data) {
|
|
46308
|
+
const items = data.items;
|
|
46309
|
+
if (Array.isArray(items)) {
|
|
46310
|
+
return items.filter(
|
|
46311
|
+
(item) => item !== null && typeof item === "object"
|
|
46312
|
+
);
|
|
46313
|
+
}
|
|
46314
|
+
}
|
|
46315
|
+
if (Array.isArray(data)) {
|
|
46316
|
+
return data.filter(
|
|
46317
|
+
(item) => item !== null && typeof item === "object"
|
|
46318
|
+
);
|
|
46319
|
+
}
|
|
46320
|
+
if (data && typeof data === "object") {
|
|
46321
|
+
return [data];
|
|
46322
|
+
}
|
|
46323
|
+
return [];
|
|
46324
|
+
}
|
|
46325
|
+
|
|
46326
|
+
// src/output/formatter.ts
|
|
46327
|
+
function formatOutput(data, format = "table", noColor = false) {
|
|
46328
|
+
if (format === "none") {
|
|
46329
|
+
return "";
|
|
46330
|
+
}
|
|
46331
|
+
const useNoColor = noColor || !shouldUseColors();
|
|
46332
|
+
switch (format) {
|
|
46333
|
+
case "json":
|
|
46334
|
+
return formatJSON(data);
|
|
46335
|
+
case "yaml":
|
|
46336
|
+
return formatYAML(data);
|
|
46337
|
+
case "table":
|
|
46338
|
+
case "text":
|
|
46339
|
+
return formatTable(data, useNoColor);
|
|
46340
|
+
case "tsv":
|
|
46341
|
+
return formatTSV(data);
|
|
46342
|
+
case "spec":
|
|
46343
|
+
return formatJSON(data);
|
|
46344
|
+
default:
|
|
46345
|
+
return formatTable(data, useNoColor);
|
|
46346
|
+
}
|
|
46347
|
+
}
|
|
46348
|
+
function formatJSON(data) {
|
|
46349
|
+
return JSON.stringify(data, null, 2);
|
|
46350
|
+
}
|
|
46351
|
+
function formatYAML(data) {
|
|
46352
|
+
return import_yaml2.default.stringify(data, { indent: 2 });
|
|
46353
|
+
}
|
|
46354
|
+
function extractItems2(data) {
|
|
46355
|
+
if (data && typeof data === "object" && "items" in data) {
|
|
46356
|
+
const items = data.items;
|
|
46357
|
+
if (Array.isArray(items)) {
|
|
46358
|
+
return items.filter(
|
|
46359
|
+
(item) => item !== null && typeof item === "object"
|
|
46360
|
+
);
|
|
46361
|
+
}
|
|
46362
|
+
}
|
|
46363
|
+
if (Array.isArray(data)) {
|
|
46364
|
+
return data.filter(
|
|
46365
|
+
(item) => item !== null && typeof item === "object"
|
|
46366
|
+
);
|
|
46367
|
+
}
|
|
46368
|
+
if (data && typeof data === "object") {
|
|
46369
|
+
return [data];
|
|
46370
|
+
}
|
|
46371
|
+
return [];
|
|
46372
|
+
}
|
|
46373
|
+
function formatTable(data, noColor = false) {
|
|
46374
|
+
return formatResourceTable(data, noColor);
|
|
46375
|
+
}
|
|
46376
|
+
function formatTSV(data) {
|
|
46377
|
+
const items = extractItems2(data);
|
|
46378
|
+
if (items.length === 0) {
|
|
46379
|
+
return "";
|
|
46380
|
+
}
|
|
46381
|
+
const allKeys = /* @__PURE__ */ new Set();
|
|
46382
|
+
for (const item of items) {
|
|
46383
|
+
Object.keys(item).forEach((k) => allKeys.add(k));
|
|
46384
|
+
}
|
|
46385
|
+
const priority = ["name", "namespace", "status", "created", "modified"];
|
|
46386
|
+
const headers = [
|
|
46387
|
+
...priority.filter((p) => allKeys.has(p)),
|
|
46388
|
+
...[...allKeys].filter((k) => !priority.includes(k)).sort()
|
|
46389
|
+
];
|
|
46390
|
+
const lines = [];
|
|
46391
|
+
for (const item of items) {
|
|
46392
|
+
const values = headers.map((h) => {
|
|
46393
|
+
const val = item[h];
|
|
46394
|
+
if (val === null || val === void 0) return "";
|
|
46395
|
+
if (typeof val === "object") return JSON.stringify(val);
|
|
46396
|
+
return String(val);
|
|
46397
|
+
});
|
|
46398
|
+
lines.push(values.join(" "));
|
|
46399
|
+
}
|
|
46400
|
+
return lines.join("\n");
|
|
46401
|
+
}
|
|
46402
|
+
function parseOutputFormat(format) {
|
|
46403
|
+
switch (format.toLowerCase()) {
|
|
46404
|
+
case "json":
|
|
46405
|
+
return "json";
|
|
46406
|
+
case "yaml":
|
|
46407
|
+
return "yaml";
|
|
46408
|
+
case "table":
|
|
46409
|
+
case "text":
|
|
46410
|
+
case "":
|
|
46411
|
+
return "table";
|
|
46412
|
+
case "tsv":
|
|
46413
|
+
return "tsv";
|
|
46414
|
+
case "none":
|
|
46415
|
+
return "none";
|
|
46416
|
+
default:
|
|
46417
|
+
return "table";
|
|
46418
|
+
}
|
|
46419
|
+
}
|
|
46420
|
+
function formatAPIError(statusCode, body, operation) {
|
|
46421
|
+
const lines = [];
|
|
46422
|
+
lines.push(`ERROR: ${operation} failed (HTTP ${statusCode})`);
|
|
46423
|
+
if (body && typeof body === "object") {
|
|
46424
|
+
const errResp = body;
|
|
46425
|
+
if (errResp.message) {
|
|
46426
|
+
lines.push(` Message: ${errResp.message}`);
|
|
46427
|
+
}
|
|
46428
|
+
if (errResp.code) {
|
|
46429
|
+
lines.push(` Code: ${errResp.code}`);
|
|
46430
|
+
}
|
|
46431
|
+
if (errResp.details) {
|
|
46432
|
+
lines.push(` Details: ${errResp.details}`);
|
|
46433
|
+
}
|
|
46434
|
+
}
|
|
46435
|
+
switch (statusCode) {
|
|
46436
|
+
case 401:
|
|
46437
|
+
lines.push(
|
|
46438
|
+
"\nHint: Authentication failed. Check your credentials with 'login profile show'"
|
|
46439
|
+
);
|
|
46440
|
+
break;
|
|
46441
|
+
case 403:
|
|
46442
|
+
lines.push(
|
|
46443
|
+
"\nHint: Permission denied. You may not have access to this resource."
|
|
46444
|
+
);
|
|
46445
|
+
break;
|
|
46446
|
+
case 404:
|
|
46447
|
+
lines.push(
|
|
46448
|
+
"\nHint: Resource not found. Verify the name and namespace are correct."
|
|
46449
|
+
);
|
|
46450
|
+
break;
|
|
46451
|
+
case 409:
|
|
46452
|
+
lines.push(
|
|
46453
|
+
"\nHint: Conflict - resource may already exist or be in a conflicting state."
|
|
46454
|
+
);
|
|
46455
|
+
break;
|
|
46456
|
+
case 429:
|
|
46457
|
+
lines.push("\nHint: Rate limited. Please wait and try again.");
|
|
46458
|
+
break;
|
|
46459
|
+
case 500:
|
|
46460
|
+
case 502:
|
|
46461
|
+
case 503:
|
|
46462
|
+
lines.push(
|
|
46463
|
+
"\nHint: Server error. Please try again later or contact support."
|
|
46464
|
+
);
|
|
46465
|
+
break;
|
|
46466
|
+
}
|
|
46467
|
+
return lines.join("\n");
|
|
46468
|
+
}
|
|
46469
|
+
|
|
46470
|
+
// src/output/spec.ts
|
|
46471
|
+
function buildCommandSpec(options) {
|
|
46472
|
+
const spec = {
|
|
46473
|
+
command: options.command,
|
|
46474
|
+
description: options.description,
|
|
46475
|
+
usage: options.usage ?? `xcsh ${options.command} [options]`,
|
|
46476
|
+
flags: options.flags ?? [],
|
|
46477
|
+
examples: options.examples ?? [],
|
|
46478
|
+
outputFormats: options.outputFormats ?? ["table", "json", "yaml"]
|
|
46479
|
+
};
|
|
46480
|
+
if (options.related !== void 0) {
|
|
46481
|
+
spec.related = options.related;
|
|
46482
|
+
}
|
|
46483
|
+
if (options.category !== void 0) {
|
|
46484
|
+
spec.category = options.category;
|
|
46485
|
+
}
|
|
46486
|
+
return spec;
|
|
46487
|
+
}
|
|
46488
|
+
function formatSpec(spec) {
|
|
46489
|
+
return JSON.stringify(spec, null, 2);
|
|
46490
|
+
}
|
|
46491
|
+
function buildCloudstatusSpecs() {
|
|
46492
|
+
return {
|
|
46493
|
+
status: buildCommandSpec({
|
|
46494
|
+
command: "cloudstatus status",
|
|
46495
|
+
description: "Get the overall health indicator for F5 Distributed Cloud services. Returns status level (operational, degraded, major outage) with description.",
|
|
46496
|
+
usage: "xcsh cloudstatus status [--quiet]",
|
|
46497
|
+
flags: [
|
|
46498
|
+
{
|
|
46499
|
+
name: "--quiet",
|
|
46500
|
+
alias: "-q",
|
|
46501
|
+
description: "Return exit code only (0=operational, 1=degraded, 2=outage)",
|
|
46502
|
+
type: "boolean"
|
|
46503
|
+
}
|
|
46504
|
+
],
|
|
46505
|
+
examples: [
|
|
46506
|
+
{
|
|
46507
|
+
command: "xcsh cloudstatus status",
|
|
46508
|
+
description: "Check current F5 XC service status"
|
|
46509
|
+
},
|
|
46510
|
+
{
|
|
46511
|
+
command: "xcsh cloudstatus status --quiet && echo 'All systems operational'",
|
|
46512
|
+
description: "Use in scripts for health checks"
|
|
46513
|
+
},
|
|
46514
|
+
{
|
|
46515
|
+
command: "xcsh cloudstatus status --output json",
|
|
46516
|
+
description: "Get status as JSON for automation"
|
|
46517
|
+
}
|
|
46518
|
+
],
|
|
46519
|
+
category: "cloudstatus",
|
|
46520
|
+
related: [
|
|
46521
|
+
"cloudstatus summary",
|
|
46522
|
+
"cloudstatus components",
|
|
46523
|
+
"cloudstatus incidents"
|
|
46524
|
+
]
|
|
46525
|
+
}),
|
|
46526
|
+
summary: buildCommandSpec({
|
|
46527
|
+
command: "cloudstatus summary",
|
|
46528
|
+
description: "Get complete status summary including overall health, component status, and active incidents.",
|
|
46529
|
+
usage: "xcsh cloudstatus summary",
|
|
46530
|
+
examples: [
|
|
46531
|
+
{
|
|
46532
|
+
command: "xcsh cloudstatus summary",
|
|
46533
|
+
description: "View full infrastructure health overview"
|
|
46534
|
+
},
|
|
46535
|
+
{
|
|
46536
|
+
command: "xcsh cloudstatus summary --output json",
|
|
46537
|
+
description: "Get complete summary as JSON"
|
|
46538
|
+
}
|
|
46539
|
+
],
|
|
46540
|
+
category: "cloudstatus",
|
|
46541
|
+
related: ["cloudstatus status", "cloudstatus components"]
|
|
46542
|
+
}),
|
|
46543
|
+
components: buildCommandSpec({
|
|
46544
|
+
command: "cloudstatus components",
|
|
46545
|
+
description: "List all infrastructure components and their current operational status.",
|
|
46546
|
+
usage: "xcsh cloudstatus components",
|
|
46547
|
+
examples: [
|
|
46548
|
+
{
|
|
46549
|
+
command: "xcsh cloudstatus components",
|
|
46550
|
+
description: "List all components with status"
|
|
46551
|
+
},
|
|
46552
|
+
{
|
|
46553
|
+
command: "xcsh cloudstatus components --output json",
|
|
46554
|
+
description: "Get components as JSON for monitoring integration"
|
|
46555
|
+
}
|
|
46556
|
+
],
|
|
46557
|
+
category: "cloudstatus",
|
|
46558
|
+
related: ["cloudstatus status", "cloudstatus summary"]
|
|
46559
|
+
}),
|
|
46560
|
+
incidents: buildCommandSpec({
|
|
46561
|
+
command: "cloudstatus incidents",
|
|
46562
|
+
description: "List active and recent incidents affecting F5 Distributed Cloud services.",
|
|
46563
|
+
usage: "xcsh cloudstatus incidents",
|
|
46564
|
+
examples: [
|
|
46565
|
+
{
|
|
46566
|
+
command: "xcsh cloudstatus incidents",
|
|
46567
|
+
description: "View active incidents"
|
|
46568
|
+
},
|
|
46569
|
+
{
|
|
46570
|
+
command: "xcsh cloudstatus incidents --output json",
|
|
46571
|
+
description: "Get incidents as JSON for alerting systems"
|
|
46572
|
+
}
|
|
46573
|
+
],
|
|
46574
|
+
category: "cloudstatus",
|
|
46575
|
+
related: ["cloudstatus status", "cloudstatus maintenance"]
|
|
46576
|
+
}),
|
|
46577
|
+
maintenance: buildCommandSpec({
|
|
46578
|
+
command: "cloudstatus maintenance",
|
|
46579
|
+
description: "List scheduled maintenance windows for F5 Distributed Cloud services.",
|
|
46580
|
+
usage: "xcsh cloudstatus maintenance",
|
|
46581
|
+
examples: [
|
|
46582
|
+
{
|
|
46583
|
+
command: "xcsh cloudstatus maintenance",
|
|
46584
|
+
description: "View upcoming maintenance windows"
|
|
46585
|
+
},
|
|
46586
|
+
{
|
|
46587
|
+
command: "xcsh cloudstatus maintenance --output json",
|
|
46588
|
+
description: "Get maintenance schedule as JSON"
|
|
46589
|
+
}
|
|
46590
|
+
],
|
|
46591
|
+
category: "cloudstatus",
|
|
46592
|
+
related: ["cloudstatus status", "cloudstatus incidents"]
|
|
46593
|
+
})
|
|
46594
|
+
};
|
|
46595
|
+
}
|
|
46596
|
+
function buildLoginSpecs() {
|
|
46597
|
+
return {
|
|
46598
|
+
banner: buildCommandSpec({
|
|
46599
|
+
command: "login banner",
|
|
46600
|
+
description: "Display xcsh banner with logo and connection information.",
|
|
46601
|
+
usage: "xcsh login banner",
|
|
46602
|
+
examples: [
|
|
46603
|
+
{
|
|
46604
|
+
command: "xcsh login banner",
|
|
46605
|
+
description: "Show the xcsh welcome banner"
|
|
46606
|
+
}
|
|
46607
|
+
],
|
|
46608
|
+
category: "login",
|
|
46609
|
+
related: ["login profile show"]
|
|
46610
|
+
}),
|
|
46611
|
+
"profile list": buildCommandSpec({
|
|
46612
|
+
command: "login profile list",
|
|
46613
|
+
description: "List all saved connection profiles.",
|
|
46614
|
+
usage: "xcsh login profile list",
|
|
46615
|
+
examples: [
|
|
46616
|
+
{
|
|
46617
|
+
command: "xcsh login profile list",
|
|
46618
|
+
description: "List saved profiles"
|
|
46619
|
+
},
|
|
46620
|
+
{
|
|
46621
|
+
command: "xcsh login profile list --output json",
|
|
46622
|
+
description: "Get profiles as JSON"
|
|
46623
|
+
}
|
|
46624
|
+
],
|
|
46625
|
+
category: "login",
|
|
46626
|
+
related: [
|
|
46627
|
+
"login profile show",
|
|
46628
|
+
"login profile create",
|
|
46629
|
+
"login profile use"
|
|
46630
|
+
]
|
|
46631
|
+
}),
|
|
46632
|
+
"profile show": buildCommandSpec({
|
|
46633
|
+
command: "login profile show",
|
|
46634
|
+
description: "Show current connection profile and authentication status.",
|
|
46635
|
+
usage: "xcsh login profile show [name]",
|
|
46636
|
+
flags: [
|
|
46637
|
+
{
|
|
46638
|
+
name: "name",
|
|
46639
|
+
description: "Profile name to show (optional, defaults to active)",
|
|
46640
|
+
type: "string"
|
|
46641
|
+
}
|
|
46642
|
+
],
|
|
46643
|
+
examples: [
|
|
46644
|
+
{
|
|
46645
|
+
command: "xcsh login profile show",
|
|
46646
|
+
description: "Show active profile"
|
|
46647
|
+
},
|
|
46648
|
+
{
|
|
46649
|
+
command: "xcsh login profile show production",
|
|
46650
|
+
description: "Show specific profile"
|
|
46651
|
+
}
|
|
46652
|
+
],
|
|
46653
|
+
category: "login",
|
|
46654
|
+
related: ["login profile list", "login profile use"]
|
|
46655
|
+
}),
|
|
46656
|
+
"profile create": buildCommandSpec({
|
|
46657
|
+
command: "login profile create",
|
|
46658
|
+
description: "Create a new connection profile with URL and credentials.",
|
|
46659
|
+
usage: "xcsh login profile create <name>",
|
|
46660
|
+
flags: [
|
|
46661
|
+
{
|
|
46662
|
+
name: "name",
|
|
46663
|
+
description: "Profile name",
|
|
46664
|
+
type: "string",
|
|
46665
|
+
required: true
|
|
46666
|
+
}
|
|
46667
|
+
],
|
|
46668
|
+
examples: [
|
|
46669
|
+
{
|
|
46670
|
+
command: "xcsh login profile create production",
|
|
46671
|
+
description: "Create a new profile named 'production'"
|
|
46672
|
+
}
|
|
46673
|
+
],
|
|
46674
|
+
category: "login",
|
|
46675
|
+
related: ["login profile list", "login profile use"]
|
|
46676
|
+
}),
|
|
46677
|
+
"profile use": buildCommandSpec({
|
|
46678
|
+
command: "login profile use",
|
|
46679
|
+
description: "Switch to a different connection profile.",
|
|
46680
|
+
usage: "xcsh login profile use <name>",
|
|
46681
|
+
flags: [
|
|
46682
|
+
{
|
|
46683
|
+
name: "name",
|
|
46684
|
+
description: "Profile name to activate",
|
|
46685
|
+
type: "string",
|
|
46686
|
+
required: true
|
|
46687
|
+
}
|
|
46688
|
+
],
|
|
46689
|
+
examples: [
|
|
46690
|
+
{
|
|
46691
|
+
command: "xcsh login profile use staging",
|
|
46692
|
+
description: "Switch to staging profile"
|
|
46693
|
+
}
|
|
46694
|
+
],
|
|
46695
|
+
category: "login",
|
|
46696
|
+
related: ["login profile list", "login profile show"]
|
|
46697
|
+
}),
|
|
46698
|
+
"context show": buildCommandSpec({
|
|
46699
|
+
command: "login context show",
|
|
46700
|
+
description: "Show the current default namespace context.",
|
|
46701
|
+
usage: "xcsh login context show",
|
|
46702
|
+
examples: [
|
|
46703
|
+
{
|
|
46704
|
+
command: "xcsh login context show",
|
|
46705
|
+
description: "Display current namespace"
|
|
46706
|
+
}
|
|
46707
|
+
],
|
|
46708
|
+
category: "login",
|
|
46709
|
+
related: ["login context set", "login context list"]
|
|
46710
|
+
}),
|
|
46711
|
+
"context set": buildCommandSpec({
|
|
46712
|
+
command: "login context set",
|
|
46713
|
+
description: "Set the default namespace for subsequent operations.",
|
|
46714
|
+
usage: "xcsh login context set <namespace>",
|
|
46715
|
+
flags: [
|
|
46716
|
+
{
|
|
46717
|
+
name: "namespace",
|
|
46718
|
+
description: "Namespace to set as default",
|
|
46719
|
+
type: "string",
|
|
46720
|
+
required: true
|
|
46721
|
+
}
|
|
46722
|
+
],
|
|
46723
|
+
examples: [
|
|
46724
|
+
{
|
|
46725
|
+
command: "xcsh login context set production",
|
|
46726
|
+
description: "Set production as default namespace"
|
|
46727
|
+
}
|
|
46728
|
+
],
|
|
46729
|
+
category: "login",
|
|
46730
|
+
related: ["login context show", "login context list"]
|
|
46731
|
+
})
|
|
46732
|
+
};
|
|
46733
|
+
}
|
|
46734
|
+
function getCommandSpec(commandPath) {
|
|
46735
|
+
const cloudstatusSpecs = buildCloudstatusSpecs();
|
|
46736
|
+
const loginSpecs = buildLoginSpecs();
|
|
46737
|
+
const normalized = commandPath.toLowerCase().trim();
|
|
46738
|
+
if (normalized.startsWith("cloudstatus ")) {
|
|
46739
|
+
const subcommand = normalized.replace("cloudstatus ", "");
|
|
46740
|
+
return cloudstatusSpecs[subcommand];
|
|
46741
|
+
}
|
|
46742
|
+
if (normalized.startsWith("login ")) {
|
|
46743
|
+
const subcommand = normalized.replace("login ", "");
|
|
46744
|
+
return loginSpecs[subcommand];
|
|
46745
|
+
}
|
|
46746
|
+
return void 0;
|
|
46747
|
+
}
|
|
46748
|
+
|
|
46027
46749
|
// src/repl/session.ts
|
|
46028
46750
|
var NAMESPACE_CACHE_TTL = 5 * 60 * 1e3;
|
|
46029
46751
|
var REPLSession = class {
|
|
@@ -46037,7 +46759,7 @@ var REPLSession = class {
|
|
|
46037
46759
|
_serverUrl = "";
|
|
46038
46760
|
_apiToken = "";
|
|
46039
46761
|
_apiClient = null;
|
|
46040
|
-
_outputFormat = "
|
|
46762
|
+
_outputFormat = "table";
|
|
46041
46763
|
_debug = false;
|
|
46042
46764
|
_profileManager;
|
|
46043
46765
|
_activeProfile = null;
|
|
@@ -46051,7 +46773,7 @@ var REPLSession = class {
|
|
|
46051
46773
|
this._profileManager = getProfileManager();
|
|
46052
46774
|
this._serverUrl = config.serverUrl ?? process.env[`${ENV_PREFIX}_API_URL`] ?? "";
|
|
46053
46775
|
this._apiToken = config.apiToken ?? process.env[`${ENV_PREFIX}_API_TOKEN`] ?? "";
|
|
46054
|
-
this._outputFormat = config.outputFormat ?? "
|
|
46776
|
+
this._outputFormat = config.outputFormat ?? getOutputFormatFromEnv() ?? "table";
|
|
46055
46777
|
this._debug = config.debug ?? process.env[`${ENV_PREFIX}_DEBUG`] === "true";
|
|
46056
46778
|
if (this._serverUrl) {
|
|
46057
46779
|
this._tenant = this.extractTenant(this._serverUrl);
|
|
@@ -46900,7 +47622,7 @@ function formatConfigSection() {
|
|
|
46900
47622
|
}
|
|
46901
47623
|
|
|
46902
47624
|
// src/repl/help.ts
|
|
46903
|
-
function
|
|
47625
|
+
function wrapText3(text, width, indent) {
|
|
46904
47626
|
const prefix = " ".repeat(indent);
|
|
46905
47627
|
const words = text.split(/\s+/);
|
|
46906
47628
|
const lines = [];
|
|
@@ -46924,7 +47646,7 @@ function formatRootHelp() {
|
|
|
46924
47646
|
colorBoldWhite(`${CLI_NAME} - ${CLI_FULL_NAME} v${CLI_VERSION}`),
|
|
46925
47647
|
"",
|
|
46926
47648
|
"DESCRIPTION",
|
|
46927
|
-
...
|
|
47649
|
+
...wrapText3(CLI_DESCRIPTION_LONG, 80, 2),
|
|
46928
47650
|
"",
|
|
46929
47651
|
"USAGE",
|
|
46930
47652
|
` ${CLI_NAME} Enter interactive REPL mode`,
|
|
@@ -46968,7 +47690,8 @@ function formatGlobalFlags() {
|
|
|
46968
47690
|
" -h, --help Show this help",
|
|
46969
47691
|
" --no-color Disable color output",
|
|
46970
47692
|
" -o, --output <fmt> Output format (json, yaml, table)",
|
|
46971
|
-
" -ns, --namespace <ns> Target namespace"
|
|
47693
|
+
" -ns, --namespace <ns> Target namespace",
|
|
47694
|
+
" --spec Output command specification as JSON (for AI)"
|
|
46972
47695
|
];
|
|
46973
47696
|
}
|
|
46974
47697
|
function formatEnvironmentVariables() {
|
|
@@ -47233,7 +47956,7 @@ function formatDomainsSection() {
|
|
|
47233
47956
|
function formatCustomDomainHelp(domain) {
|
|
47234
47957
|
const output = ["", colorBoldWhite(domain.name), ""];
|
|
47235
47958
|
output.push("DESCRIPTION");
|
|
47236
|
-
output.push(...
|
|
47959
|
+
output.push(...wrapText3(domain.description, 80, 2));
|
|
47237
47960
|
output.push("");
|
|
47238
47961
|
output.push("USAGE");
|
|
47239
47962
|
output.push(` ${CLI_NAME} ${domain.name} <command> [options]`);
|
|
@@ -47263,7 +47986,7 @@ function formatSubcommandHelp(domainName, subcommand) {
|
|
|
47263
47986
|
""
|
|
47264
47987
|
];
|
|
47265
47988
|
output.push("DESCRIPTION");
|
|
47266
|
-
output.push(...
|
|
47989
|
+
output.push(...wrapText3(subcommand.description, 80, 2));
|
|
47267
47990
|
output.push("");
|
|
47268
47991
|
output.push("USAGE");
|
|
47269
47992
|
output.push(
|
|
@@ -47982,7 +48705,7 @@ var contextSubcommands = {
|
|
|
47982
48705
|
};
|
|
47983
48706
|
|
|
47984
48707
|
// src/config/settings.ts
|
|
47985
|
-
var
|
|
48708
|
+
var import_yaml3 = __toESM(require_dist(), 1);
|
|
47986
48709
|
import { homedir as homedir3 } from "os";
|
|
47987
48710
|
import { join as join3 } from "path";
|
|
47988
48711
|
var LOGO_MODES = [
|
|
@@ -48013,7 +48736,7 @@ function loadSettingsSync() {
|
|
|
48013
48736
|
configPath,
|
|
48014
48737
|
"utf-8"
|
|
48015
48738
|
);
|
|
48016
|
-
const parsed =
|
|
48739
|
+
const parsed = import_yaml3.default.parse(content);
|
|
48017
48740
|
return {
|
|
48018
48741
|
...DEFAULT_SETTINGS,
|
|
48019
48742
|
...validateSettings(parsed)
|
|
@@ -48880,6 +49603,34 @@ function calculateRegionalStatus(components) {
|
|
|
48880
49603
|
}
|
|
48881
49604
|
|
|
48882
49605
|
// src/domains/cloudstatus/index.ts
|
|
49606
|
+
function parseOutputArgs(args, session) {
|
|
49607
|
+
let format;
|
|
49608
|
+
let spec = false;
|
|
49609
|
+
const filteredArgs = [];
|
|
49610
|
+
for (let i = 0; i < args.length; i++) {
|
|
49611
|
+
const arg = args[i] ?? "";
|
|
49612
|
+
const nextArg = args[i + 1];
|
|
49613
|
+
if (arg === "--output" || arg === "-o") {
|
|
49614
|
+
if (nextArg) {
|
|
49615
|
+
format = parseOutputFormat(nextArg);
|
|
49616
|
+
i++;
|
|
49617
|
+
}
|
|
49618
|
+
} else if (arg === "--spec") {
|
|
49619
|
+
spec = true;
|
|
49620
|
+
} else if (arg.startsWith("--output=")) {
|
|
49621
|
+
format = parseOutputFormat(arg.split("=")[1] ?? "table");
|
|
49622
|
+
} else if (arg.startsWith("-o=")) {
|
|
49623
|
+
format = parseOutputFormat(arg.split("=")[1] ?? "table");
|
|
49624
|
+
} else {
|
|
49625
|
+
filteredArgs.push(arg);
|
|
49626
|
+
}
|
|
49627
|
+
}
|
|
49628
|
+
return {
|
|
49629
|
+
format: format ?? session.getOutputFormat(),
|
|
49630
|
+
spec,
|
|
49631
|
+
filteredArgs
|
|
49632
|
+
};
|
|
49633
|
+
}
|
|
48883
49634
|
var cloudstatusClient = null;
|
|
48884
49635
|
function getClient() {
|
|
48885
49636
|
if (!cloudstatusClient) {
|
|
@@ -48895,8 +49646,14 @@ var statusCommand = {
|
|
|
48895
49646
|
usage: "[--quiet]",
|
|
48896
49647
|
aliases: ["st"],
|
|
48897
49648
|
async execute(args, session) {
|
|
48898
|
-
const
|
|
48899
|
-
const
|
|
49649
|
+
const { format, spec, filteredArgs } = parseOutputArgs(args, session);
|
|
49650
|
+
const quiet = filteredArgs.includes("--quiet") || filteredArgs.includes("-q");
|
|
49651
|
+
if (spec) {
|
|
49652
|
+
const cmdSpec = getCommandSpec("cloudstatus status");
|
|
49653
|
+
if (cmdSpec) {
|
|
49654
|
+
return successResult([formatSpec(cmdSpec)]);
|
|
49655
|
+
}
|
|
49656
|
+
}
|
|
48900
49657
|
try {
|
|
48901
49658
|
const client = getClient();
|
|
48902
49659
|
const response = await client.getStatus();
|
|
@@ -48946,8 +49703,14 @@ var summaryCommand = {
|
|
|
48946
49703
|
usage: "[--brief]",
|
|
48947
49704
|
aliases: ["sum"],
|
|
48948
49705
|
async execute(args, session) {
|
|
48949
|
-
const
|
|
48950
|
-
const
|
|
49706
|
+
const { format, spec, filteredArgs } = parseOutputArgs(args, session);
|
|
49707
|
+
const brief = filteredArgs.includes("--brief") || filteredArgs.includes("-b");
|
|
49708
|
+
if (spec) {
|
|
49709
|
+
const cmdSpec = getCommandSpec("cloudstatus summary");
|
|
49710
|
+
if (cmdSpec) {
|
|
49711
|
+
return successResult([formatSpec(cmdSpec)]);
|
|
49712
|
+
}
|
|
49713
|
+
}
|
|
48951
49714
|
try {
|
|
48952
49715
|
const client = getClient();
|
|
48953
49716
|
const response = await client.getSummary();
|
|
@@ -48975,8 +49738,14 @@ var componentsCommand = {
|
|
|
48975
49738
|
usage: "[--degraded-only]",
|
|
48976
49739
|
aliases: ["comp"],
|
|
48977
49740
|
async execute(args, session) {
|
|
48978
|
-
const
|
|
48979
|
-
const
|
|
49741
|
+
const { format, spec, filteredArgs } = parseOutputArgs(args, session);
|
|
49742
|
+
const degradedOnly = filteredArgs.includes("--degraded-only") || filteredArgs.includes("-d");
|
|
49743
|
+
if (spec) {
|
|
49744
|
+
const cmdSpec = getCommandSpec("cloudstatus components");
|
|
49745
|
+
if (cmdSpec) {
|
|
49746
|
+
return successResult([formatSpec(cmdSpec)]);
|
|
49747
|
+
}
|
|
49748
|
+
}
|
|
48980
49749
|
try {
|
|
48981
49750
|
const client = getClient();
|
|
48982
49751
|
const response = await client.getComponents();
|
|
@@ -49018,8 +49787,14 @@ var incidentsCommand = {
|
|
|
49018
49787
|
usage: "[--active-only]",
|
|
49019
49788
|
aliases: ["inc"],
|
|
49020
49789
|
async execute(args, session) {
|
|
49021
|
-
const
|
|
49022
|
-
const
|
|
49790
|
+
const { format, spec, filteredArgs } = parseOutputArgs(args, session);
|
|
49791
|
+
const activeOnly = filteredArgs.includes("--active-only") || filteredArgs.includes("-a");
|
|
49792
|
+
if (spec) {
|
|
49793
|
+
const cmdSpec = getCommandSpec("cloudstatus incidents");
|
|
49794
|
+
if (cmdSpec) {
|
|
49795
|
+
return successResult([formatSpec(cmdSpec)]);
|
|
49796
|
+
}
|
|
49797
|
+
}
|
|
49023
49798
|
try {
|
|
49024
49799
|
const client = getClient();
|
|
49025
49800
|
const response = activeOnly ? await client.getUnresolvedIncidents() : await client.getIncidents();
|
|
@@ -49059,8 +49834,14 @@ var maintenanceCommand = {
|
|
|
49059
49834
|
usage: "[--upcoming]",
|
|
49060
49835
|
aliases: ["maint"],
|
|
49061
49836
|
async execute(args, session) {
|
|
49062
|
-
const
|
|
49063
|
-
const
|
|
49837
|
+
const { format, spec, filteredArgs } = parseOutputArgs(args, session);
|
|
49838
|
+
const upcomingOnly = filteredArgs.includes("--upcoming") || filteredArgs.includes("-u");
|
|
49839
|
+
if (spec) {
|
|
49840
|
+
const cmdSpec = getCommandSpec("cloudstatus maintenance");
|
|
49841
|
+
if (cmdSpec) {
|
|
49842
|
+
return successResult([formatSpec(cmdSpec)]);
|
|
49843
|
+
}
|
|
49844
|
+
}
|
|
49064
49845
|
try {
|
|
49065
49846
|
const client = getClient();
|
|
49066
49847
|
const response = upcomingOnly ? await client.getUpcomingMaintenances() : await client.getMaintenances();
|
|
@@ -49532,7 +50313,7 @@ _xcsh_completions() {
|
|
|
49532
50313
|
local commands="${domainNames} ${allAliases.join(" ")} help quit exit clear history"
|
|
49533
50314
|
local actions="${actions}"
|
|
49534
50315
|
local builtins="help quit exit clear history context ctx"
|
|
49535
|
-
local global_flags="--help -h --version -v --no-color --output -o --namespace -ns"
|
|
50316
|
+
local global_flags="--help -h --version -v --no-color --output -o --namespace -ns --spec"
|
|
49536
50317
|
|
|
49537
50318
|
# Handle completion based on position
|
|
49538
50319
|
case \${cword} in
|
|
@@ -49563,7 +50344,7 @@ ${customDomainCompletions.join("\n")}
|
|
|
49563
50344
|
*)
|
|
49564
50345
|
# Third+ word: flags
|
|
49565
50346
|
if [[ "\${cur}" == -* ]]; then
|
|
49566
|
-
local action_flags="--name -n --namespace -ns --output -o --json --yaml --limit --label"
|
|
50347
|
+
local action_flags="--name -n --namespace -ns --output -o --json --yaml --limit --label --spec"
|
|
49567
50348
|
COMPREPLY=($(compgen -W "\${action_flags}" -- "\${cur}"))
|
|
49568
50349
|
fi
|
|
49569
50350
|
return 0
|
|
@@ -49617,6 +50398,7 @@ _xcsh() {
|
|
|
49617
50398
|
'--no-color[Disable color output]'
|
|
49618
50399
|
'(-o --output)'{-o,--output}'[Output format]:format:(json yaml table)'
|
|
49619
50400
|
'(-ns --namespace)'{-ns,--namespace}'[Namespace]:namespace:_xcsh_namespaces'
|
|
50401
|
+
'--spec[Output command specification as JSON for AI assistants]'
|
|
49620
50402
|
)
|
|
49621
50403
|
|
|
49622
50404
|
_arguments -C \\
|
|
@@ -49667,6 +50449,7 @@ ${customDomainCompletions.join("\n")}
|
|
|
49667
50449
|
'--limit[Maximum results]:limit:'
|
|
49668
50450
|
'--label[Filter by label]:label:'
|
|
49669
50451
|
'(-f --file)'{-f,--file}'[Configuration file]:file:_files'
|
|
50452
|
+
'--spec[Output command specification as JSON for AI assistants]'
|
|
49670
50453
|
)
|
|
49671
50454
|
_arguments "\${action_opts[@]}"
|
|
49672
50455
|
;;
|
|
@@ -49730,6 +50513,7 @@ complete -c xcsh -s v -l version -d 'Show version number'
|
|
|
49730
50513
|
complete -c xcsh -l no-color -d 'Disable color output'
|
|
49731
50514
|
complete -c xcsh -s o -l output -d 'Output format' -xa 'json yaml table'
|
|
49732
50515
|
complete -c xcsh -l namespace -s ns -d 'Namespace' -xa 'default system shared'
|
|
50516
|
+
complete -c xcsh -l spec -d 'Output command specification as JSON for AI assistants'
|
|
49733
50517
|
|
|
49734
50518
|
# Builtin commands
|
|
49735
50519
|
complete -c xcsh -n "__fish_use_subcommand" -a "help" -d 'Show help information'
|
|
@@ -49759,6 +50543,7 @@ complete -c xcsh -l label -d 'Filter by label'
|
|
|
49759
50543
|
complete -c xcsh -s f -l file -d 'Configuration file' -r
|
|
49760
50544
|
complete -c xcsh -l force -d 'Force deletion'
|
|
49761
50545
|
complete -c xcsh -l cascade -d 'Cascade delete'
|
|
50546
|
+
complete -c xcsh -l spec -d 'Output command specification as JSON for AI assistants'
|
|
49762
50547
|
`;
|
|
49763
50548
|
}
|
|
49764
50549
|
|
|
@@ -50925,219 +51710,6 @@ function useCompletion(options) {
|
|
|
50925
51710
|
};
|
|
50926
51711
|
}
|
|
50927
51712
|
|
|
50928
|
-
// src/output/formatter.ts
|
|
50929
|
-
var import_yaml3 = __toESM(require_dist(), 1);
|
|
50930
|
-
function formatOutput(data, format = "yaml") {
|
|
50931
|
-
if (format === "none") {
|
|
50932
|
-
return "";
|
|
50933
|
-
}
|
|
50934
|
-
switch (format) {
|
|
50935
|
-
case "json":
|
|
50936
|
-
return formatJSON(data);
|
|
50937
|
-
case "yaml":
|
|
50938
|
-
return formatYAML(data);
|
|
50939
|
-
case "table":
|
|
50940
|
-
case "text":
|
|
50941
|
-
return formatTable(data);
|
|
50942
|
-
case "tsv":
|
|
50943
|
-
return formatTSV(data);
|
|
50944
|
-
default:
|
|
50945
|
-
return formatYAML(data);
|
|
50946
|
-
}
|
|
50947
|
-
}
|
|
50948
|
-
function formatJSON(data) {
|
|
50949
|
-
return JSON.stringify(data, null, 2);
|
|
50950
|
-
}
|
|
50951
|
-
function formatYAML(data) {
|
|
50952
|
-
return import_yaml3.default.stringify(data, { indent: 2 });
|
|
50953
|
-
}
|
|
50954
|
-
function extractItems(data) {
|
|
50955
|
-
if (data && typeof data === "object" && "items" in data) {
|
|
50956
|
-
const items = data.items;
|
|
50957
|
-
if (Array.isArray(items)) {
|
|
50958
|
-
return items.filter(
|
|
50959
|
-
(item) => item !== null && typeof item === "object"
|
|
50960
|
-
);
|
|
50961
|
-
}
|
|
50962
|
-
}
|
|
50963
|
-
if (Array.isArray(data)) {
|
|
50964
|
-
return data.filter(
|
|
50965
|
-
(item) => item !== null && typeof item === "object"
|
|
50966
|
-
);
|
|
50967
|
-
}
|
|
50968
|
-
if (data && typeof data === "object") {
|
|
50969
|
-
return [data];
|
|
50970
|
-
}
|
|
50971
|
-
return [];
|
|
50972
|
-
}
|
|
50973
|
-
function getStringField(obj, key) {
|
|
50974
|
-
const value = obj[key];
|
|
50975
|
-
if (typeof value === "string") {
|
|
50976
|
-
return value;
|
|
50977
|
-
}
|
|
50978
|
-
if (value !== null && value !== void 0) {
|
|
50979
|
-
return String(value);
|
|
50980
|
-
}
|
|
50981
|
-
return "";
|
|
50982
|
-
}
|
|
50983
|
-
function formatLabels(obj) {
|
|
50984
|
-
const labels = obj["labels"];
|
|
50985
|
-
if (!labels || typeof labels !== "object") {
|
|
50986
|
-
return "";
|
|
50987
|
-
}
|
|
50988
|
-
const labelMap = labels;
|
|
50989
|
-
const entries = Object.entries(labelMap).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}:${v}`);
|
|
50990
|
-
if (entries.length === 0) {
|
|
50991
|
-
return "";
|
|
50992
|
-
}
|
|
50993
|
-
return `map[${entries.join(" ")}]`;
|
|
50994
|
-
}
|
|
50995
|
-
function wrapText3(text, maxWidth) {
|
|
50996
|
-
if (text.length <= maxWidth) {
|
|
50997
|
-
return [text];
|
|
50998
|
-
}
|
|
50999
|
-
const lines = [];
|
|
51000
|
-
let remaining = text;
|
|
51001
|
-
while (remaining.length > 0) {
|
|
51002
|
-
if (remaining.length <= maxWidth) {
|
|
51003
|
-
lines.push(remaining);
|
|
51004
|
-
break;
|
|
51005
|
-
}
|
|
51006
|
-
let breakPoint = maxWidth;
|
|
51007
|
-
for (let i = maxWidth - 1; i > 0; i--) {
|
|
51008
|
-
if (remaining[i] === " ") {
|
|
51009
|
-
breakPoint = i;
|
|
51010
|
-
break;
|
|
51011
|
-
}
|
|
51012
|
-
}
|
|
51013
|
-
lines.push(remaining.slice(0, breakPoint));
|
|
51014
|
-
remaining = remaining.slice(breakPoint).trimStart();
|
|
51015
|
-
}
|
|
51016
|
-
return lines;
|
|
51017
|
-
}
|
|
51018
|
-
function formatTable(data) {
|
|
51019
|
-
const items = extractItems(data);
|
|
51020
|
-
if (items.length === 0) {
|
|
51021
|
-
return "";
|
|
51022
|
-
}
|
|
51023
|
-
const headers = ["NAMESPACE", "NAME", "LABELS"];
|
|
51024
|
-
const widths = [9, 27, 30];
|
|
51025
|
-
const rows = [];
|
|
51026
|
-
for (const item of items) {
|
|
51027
|
-
const row = [
|
|
51028
|
-
getStringField(item, "namespace") || "<None>",
|
|
51029
|
-
getStringField(item, "name") || "<None>",
|
|
51030
|
-
formatLabels(item) || "<None>"
|
|
51031
|
-
];
|
|
51032
|
-
const wrappedCells = row.map((cell, i) => wrapText3(cell, widths[i]));
|
|
51033
|
-
const maxLines = Math.max(...wrappedCells.map((c) => c.length));
|
|
51034
|
-
const wrappedRows = [];
|
|
51035
|
-
for (let line = 0; line < maxLines; line++) {
|
|
51036
|
-
wrappedRows.push(wrappedCells.map((c) => c[line] ?? ""));
|
|
51037
|
-
}
|
|
51038
|
-
rows.push(wrappedRows);
|
|
51039
|
-
}
|
|
51040
|
-
const lines = [];
|
|
51041
|
-
const boxLine = "+" + widths.map((w) => "-".repeat(w + 2)).join("+") + "+";
|
|
51042
|
-
lines.push(boxLine);
|
|
51043
|
-
lines.push(
|
|
51044
|
-
"|" + headers.map((h, i) => {
|
|
51045
|
-
const padding = widths[i] - h.length;
|
|
51046
|
-
const leftPad = Math.floor(padding / 2);
|
|
51047
|
-
const rightPad = padding - leftPad;
|
|
51048
|
-
return " " + " ".repeat(leftPad) + h + " ".repeat(rightPad) + " ";
|
|
51049
|
-
}).join("|") + "|"
|
|
51050
|
-
);
|
|
51051
|
-
lines.push(boxLine);
|
|
51052
|
-
for (const wrappedRows of rows) {
|
|
51053
|
-
for (const row of wrappedRows) {
|
|
51054
|
-
lines.push(
|
|
51055
|
-
"|" + row.map((cell, i) => {
|
|
51056
|
-
const padding = widths[i] - cell.length;
|
|
51057
|
-
return " " + cell + " ".repeat(padding) + " ";
|
|
51058
|
-
}).join("|") + "|"
|
|
51059
|
-
);
|
|
51060
|
-
}
|
|
51061
|
-
lines.push(boxLine);
|
|
51062
|
-
}
|
|
51063
|
-
return lines.join("\n");
|
|
51064
|
-
}
|
|
51065
|
-
function formatTSV(data) {
|
|
51066
|
-
const items = extractItems(data);
|
|
51067
|
-
if (items.length === 0) {
|
|
51068
|
-
return "";
|
|
51069
|
-
}
|
|
51070
|
-
const allKeys = /* @__PURE__ */ new Set();
|
|
51071
|
-
for (const item of items) {
|
|
51072
|
-
Object.keys(item).forEach((k) => allKeys.add(k));
|
|
51073
|
-
}
|
|
51074
|
-
const priority = ["name", "namespace", "status", "created", "modified"];
|
|
51075
|
-
const headers = [
|
|
51076
|
-
...priority.filter((p) => allKeys.has(p)),
|
|
51077
|
-
...[...allKeys].filter((k) => !priority.includes(k)).sort()
|
|
51078
|
-
];
|
|
51079
|
-
const lines = [];
|
|
51080
|
-
for (const item of items) {
|
|
51081
|
-
const values = headers.map((h) => {
|
|
51082
|
-
const val = item[h];
|
|
51083
|
-
if (val === null || val === void 0) return "";
|
|
51084
|
-
if (typeof val === "object") return JSON.stringify(val);
|
|
51085
|
-
return String(val);
|
|
51086
|
-
});
|
|
51087
|
-
lines.push(values.join(" "));
|
|
51088
|
-
}
|
|
51089
|
-
return lines.join("\n");
|
|
51090
|
-
}
|
|
51091
|
-
function formatAPIError(statusCode, body, operation) {
|
|
51092
|
-
const lines = [];
|
|
51093
|
-
lines.push(`ERROR: ${operation} failed (HTTP ${statusCode})`);
|
|
51094
|
-
if (body && typeof body === "object") {
|
|
51095
|
-
const errResp = body;
|
|
51096
|
-
if (errResp.message) {
|
|
51097
|
-
lines.push(` Message: ${errResp.message}`);
|
|
51098
|
-
}
|
|
51099
|
-
if (errResp.code) {
|
|
51100
|
-
lines.push(` Code: ${errResp.code}`);
|
|
51101
|
-
}
|
|
51102
|
-
if (errResp.details) {
|
|
51103
|
-
lines.push(` Details: ${errResp.details}`);
|
|
51104
|
-
}
|
|
51105
|
-
}
|
|
51106
|
-
switch (statusCode) {
|
|
51107
|
-
case 401:
|
|
51108
|
-
lines.push(
|
|
51109
|
-
"\nHint: Authentication failed. Check your credentials with 'login profile show'"
|
|
51110
|
-
);
|
|
51111
|
-
break;
|
|
51112
|
-
case 403:
|
|
51113
|
-
lines.push(
|
|
51114
|
-
"\nHint: Permission denied. You may not have access to this resource."
|
|
51115
|
-
);
|
|
51116
|
-
break;
|
|
51117
|
-
case 404:
|
|
51118
|
-
lines.push(
|
|
51119
|
-
"\nHint: Resource not found. Verify the name and namespace are correct."
|
|
51120
|
-
);
|
|
51121
|
-
break;
|
|
51122
|
-
case 409:
|
|
51123
|
-
lines.push(
|
|
51124
|
-
"\nHint: Conflict - resource may already exist or be in a conflicting state."
|
|
51125
|
-
);
|
|
51126
|
-
break;
|
|
51127
|
-
case 429:
|
|
51128
|
-
lines.push("\nHint: Rate limited. Please wait and try again.");
|
|
51129
|
-
break;
|
|
51130
|
-
case 500:
|
|
51131
|
-
case 502:
|
|
51132
|
-
case 503:
|
|
51133
|
-
lines.push(
|
|
51134
|
-
"\nHint: Server error. Please try again later or contact support."
|
|
51135
|
-
);
|
|
51136
|
-
break;
|
|
51137
|
-
}
|
|
51138
|
-
return lines.join("\n");
|
|
51139
|
-
}
|
|
51140
|
-
|
|
51141
51713
|
// src/repl/executor.ts
|
|
51142
51714
|
var BUILTIN_COMMANDS = /* @__PURE__ */ new Set([
|
|
51143
51715
|
"help",
|
|
@@ -51687,34 +52259,66 @@ function domainToResourcePath(domain) {
|
|
|
51687
52259
|
function parseCommandArgs(args) {
|
|
51688
52260
|
let name;
|
|
51689
52261
|
let namespace;
|
|
52262
|
+
let outputFormat;
|
|
52263
|
+
let spec = false;
|
|
52264
|
+
let noColor = false;
|
|
51690
52265
|
for (let i = 0; i < args.length; i++) {
|
|
51691
52266
|
const arg = args[i] ?? "";
|
|
51692
52267
|
if (arg.startsWith("--")) {
|
|
51693
|
-
const flagName = arg.slice(2);
|
|
52268
|
+
const flagName = arg.slice(2).toLowerCase();
|
|
51694
52269
|
const nextArg = args[i + 1];
|
|
51695
|
-
|
|
51696
|
-
namespace
|
|
51697
|
-
|
|
51698
|
-
|
|
51699
|
-
|
|
51700
|
-
|
|
51701
|
-
|
|
51702
|
-
|
|
52270
|
+
switch (flagName) {
|
|
52271
|
+
case "namespace":
|
|
52272
|
+
case "ns":
|
|
52273
|
+
namespace = nextArg;
|
|
52274
|
+
i++;
|
|
52275
|
+
break;
|
|
52276
|
+
case "name":
|
|
52277
|
+
name = nextArg;
|
|
52278
|
+
i++;
|
|
52279
|
+
break;
|
|
52280
|
+
case "output":
|
|
52281
|
+
if (nextArg) {
|
|
52282
|
+
outputFormat = parseOutputFormat(nextArg);
|
|
52283
|
+
i++;
|
|
52284
|
+
}
|
|
52285
|
+
break;
|
|
52286
|
+
case "spec":
|
|
52287
|
+
spec = true;
|
|
52288
|
+
break;
|
|
52289
|
+
case "no-color":
|
|
52290
|
+
noColor = true;
|
|
52291
|
+
break;
|
|
52292
|
+
default:
|
|
52293
|
+
if (nextArg && !nextArg.startsWith("--")) {
|
|
52294
|
+
i++;
|
|
52295
|
+
}
|
|
51703
52296
|
}
|
|
51704
52297
|
} else if (arg.startsWith("-")) {
|
|
51705
52298
|
const flagName = arg.slice(1);
|
|
51706
52299
|
const nextArg = args[i + 1];
|
|
51707
|
-
|
|
51708
|
-
|
|
51709
|
-
|
|
51710
|
-
|
|
51711
|
-
|
|
52300
|
+
switch (flagName) {
|
|
52301
|
+
case "n":
|
|
52302
|
+
case "ns":
|
|
52303
|
+
namespace = nextArg;
|
|
52304
|
+
i++;
|
|
52305
|
+
break;
|
|
52306
|
+
case "o":
|
|
52307
|
+
if (nextArg) {
|
|
52308
|
+
outputFormat = parseOutputFormat(nextArg);
|
|
52309
|
+
i++;
|
|
52310
|
+
}
|
|
52311
|
+
break;
|
|
52312
|
+
default:
|
|
52313
|
+
if (nextArg && !nextArg.startsWith("-")) {
|
|
52314
|
+
i++;
|
|
52315
|
+
}
|
|
51712
52316
|
}
|
|
51713
52317
|
} else if (!name) {
|
|
51714
52318
|
name = arg;
|
|
51715
52319
|
}
|
|
51716
52320
|
}
|
|
51717
|
-
return { name, namespace };
|
|
52321
|
+
return { name, namespace, outputFormat, spec, noColor };
|
|
51718
52322
|
}
|
|
51719
52323
|
async function executeAPICommand(session, ctx, cmd) {
|
|
51720
52324
|
const client = session.getAPIClient();
|
|
@@ -51763,8 +52367,51 @@ async function executeAPICommand(session, ctx, cmd) {
|
|
|
51763
52367
|
}
|
|
51764
52368
|
}
|
|
51765
52369
|
const canonicalDomain = resolveDomain(domain) ?? domain;
|
|
51766
|
-
const { name, namespace } = parseCommandArgs(args);
|
|
52370
|
+
const { name, namespace, outputFormat, spec, noColor } = parseCommandArgs(args);
|
|
51767
52371
|
const effectiveNamespace = namespace ?? session.getNamespace();
|
|
52372
|
+
if (spec) {
|
|
52373
|
+
const commandPath = `${canonicalDomain} ${action}`;
|
|
52374
|
+
const cmdSpec = getCommandSpec(commandPath);
|
|
52375
|
+
if (cmdSpec) {
|
|
52376
|
+
return {
|
|
52377
|
+
output: [formatSpec(cmdSpec)],
|
|
52378
|
+
shouldExit: false,
|
|
52379
|
+
shouldClear: false,
|
|
52380
|
+
contextChanged: false
|
|
52381
|
+
};
|
|
52382
|
+
}
|
|
52383
|
+
const basicSpec = {
|
|
52384
|
+
command: `${CLI_NAME} ${canonicalDomain} ${action}`,
|
|
52385
|
+
description: `Execute ${action} on ${canonicalDomain} resources`,
|
|
52386
|
+
usage: `${CLI_NAME} ${canonicalDomain} ${action} [name] [options]`,
|
|
52387
|
+
flags: [
|
|
52388
|
+
{
|
|
52389
|
+
name: "--namespace",
|
|
52390
|
+
alias: "-ns",
|
|
52391
|
+
type: "string",
|
|
52392
|
+
description: "Target namespace"
|
|
52393
|
+
},
|
|
52394
|
+
{
|
|
52395
|
+
name: "--output",
|
|
52396
|
+
alias: "-o",
|
|
52397
|
+
type: "string",
|
|
52398
|
+
description: "Output format (json, yaml, table)"
|
|
52399
|
+
},
|
|
52400
|
+
{
|
|
52401
|
+
name: "--name",
|
|
52402
|
+
type: "string",
|
|
52403
|
+
description: "Resource name"
|
|
52404
|
+
}
|
|
52405
|
+
],
|
|
52406
|
+
outputFormats: ["table", "json", "yaml"]
|
|
52407
|
+
};
|
|
52408
|
+
return {
|
|
52409
|
+
output: [JSON.stringify(basicSpec, null, 2)],
|
|
52410
|
+
shouldExit: false,
|
|
52411
|
+
shouldClear: false,
|
|
52412
|
+
contextChanged: false
|
|
52413
|
+
};
|
|
52414
|
+
}
|
|
51768
52415
|
const resourcePath = domainToResourcePath(canonicalDomain);
|
|
51769
52416
|
let apiPath = `/api/config/namespaces/${effectiveNamespace}/${resourcePath}`;
|
|
51770
52417
|
try {
|
|
@@ -51849,8 +52496,8 @@ async function executeAPICommand(session, ctx, cmd) {
|
|
|
51849
52496
|
};
|
|
51850
52497
|
}
|
|
51851
52498
|
}
|
|
51852
|
-
const
|
|
51853
|
-
const formatted = formatOutput(result,
|
|
52499
|
+
const effectiveFormat = outputFormat ?? session.getOutputFormat();
|
|
52500
|
+
const formatted = formatOutput(result, effectiveFormat, noColor);
|
|
51854
52501
|
return {
|
|
51855
52502
|
output: formatted ? [formatted] : ["(no output)"],
|
|
51856
52503
|
shouldExit: false,
|
|
@@ -52241,7 +52888,7 @@ var program2 = new Command();
|
|
|
52241
52888
|
program2.configureHelp({
|
|
52242
52889
|
formatHelp: () => formatRootHelp().join("\n")
|
|
52243
52890
|
});
|
|
52244
|
-
program2.name(CLI_NAME).description("F5 Distributed Cloud Shell - Interactive CLI for F5 XC").version(CLI_VERSION, "-v, --version", "Show version number").option("--no-color", "Disable color output").option("--logo <mode>", "Logo display mode: image, ascii, none").option("-h, --help", "Show help").argument("[command...]", "Command to execute non-interactively").allowUnknownOption(true).helpOption(false).action(
|
|
52891
|
+
program2.name(CLI_NAME).description("F5 Distributed Cloud Shell - Interactive CLI for F5 XC").version(CLI_VERSION, "-v, --version", "Show version number").option("--no-color", "Disable color output").option("--logo <mode>", "Logo display mode: image, ascii, none").option("-o, --output <format>", "Output format (json, yaml, table)").option("--spec", "Output command specification as JSON (for AI)").option("-h, --help", "Show help").argument("[command...]", "Command to execute non-interactively").allowUnknownOption(true).helpOption(false).action(
|
|
52245
52892
|
async (commandArgs, options) => {
|
|
52246
52893
|
if (options.help && commandArgs.length === 0) {
|
|
52247
52894
|
formatRootHelp().forEach((line) => console.log(line));
|
|
@@ -52253,6 +52900,12 @@ program2.name(CLI_NAME).description("F5 Distributed Cloud Shell - Interactive CL
|
|
|
52253
52900
|
if (options.logo && commandArgs.length > 0) {
|
|
52254
52901
|
commandArgs.push("--logo", options.logo);
|
|
52255
52902
|
}
|
|
52903
|
+
if (options.output && commandArgs.length > 0) {
|
|
52904
|
+
commandArgs.push("--output", options.output);
|
|
52905
|
+
}
|
|
52906
|
+
if (options.spec && commandArgs.length > 0) {
|
|
52907
|
+
commandArgs.push("--spec");
|
|
52908
|
+
}
|
|
52256
52909
|
if (commandArgs.length === 0) {
|
|
52257
52910
|
if (!process.stdin.isTTY) {
|
|
52258
52911
|
console.error(
|