@robinmordasiewicz/f5xc-xcsh 6.34.0 → 6.36.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 +3 -3
- package/completions/xcsh.fish +3 -3
- package/dist/index.js +831 -729
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -44108,9 +44108,9 @@ var generatedDomains = /* @__PURE__ */ new Map([
|
|
|
44108
44108
|
["admin_console_and_ui", {
|
|
44109
44109
|
name: "admin_console_and_ui",
|
|
44110
44110
|
displayName: "Admin Console And Ui",
|
|
44111
|
-
description: "
|
|
44112
|
-
descriptionShort: "Manage static UI
|
|
44113
|
-
descriptionMedium: "Deploy and
|
|
44111
|
+
description: "Create administrative dashboard building blocks with tailored setup data and view bindings. Organize presentational materials by namespace and fetch them by name or list all available items. Define display parameters, track system object relationships, and maintain consistent portal appearance through centralized resource management workflows.",
|
|
44112
|
+
descriptionShort: "Manage static UI components for admin console",
|
|
44113
|
+
descriptionMedium: "Deploy and retrieve graphical elements within namespaces. Configure custom startup parameters and view references for display composition.",
|
|
44114
44114
|
aliases: ["console-ui", "ui-assets", "static-components"],
|
|
44115
44115
|
complexity: "simple",
|
|
44116
44116
|
isPreview: false,
|
|
@@ -44242,9 +44242,9 @@ var generatedDomains = /* @__PURE__ */ new Map([
|
|
|
44242
44242
|
["bot_and_threat_defense", {
|
|
44243
44243
|
name: "bot_and_threat_defense",
|
|
44244
44244
|
displayName: "Bot And Threat Defense",
|
|
44245
|
-
description: "Deploy
|
|
44246
|
-
descriptionShort: "
|
|
44247
|
-
descriptionMedium: "
|
|
44245
|
+
description: "Deploy namespace-scoped protection using behavioral analysis and machine learning. Provision dedicated keys for system automation and real-time intelligence feeds. Coordinate detection across protected applications through centralized managers. Configure pre-authentication checks to identify suspicious patterns before they reach backends. Enable adaptive blocking decisions based on risk scoring and historical activity profiles.",
|
|
44246
|
+
descriptionShort: "Detect and block automated attacks",
|
|
44247
|
+
descriptionMedium: "Create bot defense instances with Shape integration. Set up traffic classification rules and automated response policies for malicious actors.",
|
|
44248
44248
|
aliases: ["threat-defense", "tpm", "shape-bot"],
|
|
44249
44249
|
complexity: "moderate",
|
|
44250
44250
|
isPreview: false,
|
|
@@ -44256,9 +44256,9 @@ var generatedDomains = /* @__PURE__ */ new Map([
|
|
|
44256
44256
|
["cdn", {
|
|
44257
44257
|
name: "cdn",
|
|
44258
44258
|
displayName: "Cdn",
|
|
44259
|
-
description: "
|
|
44260
|
-
descriptionShort: "Configure caching rules and load
|
|
44261
|
-
descriptionMedium: "Define cache
|
|
44259
|
+
description: "Set up cache eligibility based on headers, cookies, and query parameters. Create expression-based rules with custom TTL settings and path matchers. Deploy load balancers that handle content distribution across origin pools. Monitor access logs and metrics, aggregate performance data, and execute cache purge operations when content updates require immediate invalidation.",
|
|
44260
|
+
descriptionShort: "Configure caching rules and load balancing",
|
|
44261
|
+
descriptionMedium: "Define cache rules, TTLs, and path matching. Manage load balancers with origin pools and purge operations.",
|
|
44262
44262
|
aliases: ["cache", "content"],
|
|
44263
44263
|
complexity: "advanced",
|
|
44264
44264
|
isPreview: false,
|
|
@@ -45166,6 +45166,51 @@ var HistoryManager = class _HistoryManager {
|
|
|
45166
45166
|
}
|
|
45167
45167
|
};
|
|
45168
45168
|
|
|
45169
|
+
// src/domains/descriptions.generated.ts
|
|
45170
|
+
var generatedDescriptions = {
|
|
45171
|
+
version: "1.0.0",
|
|
45172
|
+
generatedAt: "2025-12-30T03:58:36.781Z",
|
|
45173
|
+
cli: {
|
|
45174
|
+
"xcsh": {
|
|
45175
|
+
short: "Navigate cloud services via interactive shell",
|
|
45176
|
+
medium: "Manage multi-tenant connections, execute domain operations across 100+ services, and output results in JSON, YAML, or table format.",
|
|
45177
|
+
long: "Interact with cloud services through an intelligent shell environment. Navigate over 100 domain operations using tab completion for commands, flags, and values. Organize multiple tenant connections with named profiles and switch contexts without re-authenticating. Execute commands directly from scripts or explore interactively with history and suggestions. Configure output format as JSON, YAML, or formatted tables. Set behavior through environment variables or persistent profile settings. Generate shell completions for bash, zsh, and fish terminals."
|
|
45178
|
+
}
|
|
45179
|
+
},
|
|
45180
|
+
domains: {
|
|
45181
|
+
"login": {
|
|
45182
|
+
short: "Configure session credentials and environment profiles",
|
|
45183
|
+
medium: "Set up authentication tokens, organize named profiles for multiple tenants, and switch between target environments for CLI operations.",
|
|
45184
|
+
long: "Control authentication and session state across multiple environments. Run 'show' to display current connection details and token status. Organize credentials with 'profile' to maintain separate configurations for development, staging, and production tenants. Switch active targets via 'context' without re-authenticating. Run 'banner' for visual confirmation of the active environment. Profiles persist locally with token-based and certificate authentication support.",
|
|
45185
|
+
subcommands: {
|
|
45186
|
+
"profile": {
|
|
45187
|
+
short: "Manage saved connection configurations for authentication",
|
|
45188
|
+
medium: "Store and switch between multiple tenant connection settings. Create, list, and activate named configurations to avoid repeated credential entry.",
|
|
45189
|
+
long: "Organize tenant connections as reusable named entries for rapid environment switching. Each entry persists URLs and authentication tokens, removing manual reconfiguration overhead. Available operations: 'list' enumerates saved entries, 'show' reveals configuration details, 'create' registers new connections, 'delete' purges obsolete ones, 'active' identifies the current selection, and 'use' changes context. Ideal for workflows spanning development, staging, and production tiers."
|
|
45190
|
+
},
|
|
45191
|
+
"context": {
|
|
45192
|
+
short: "Manage default namespace for scoping operations",
|
|
45193
|
+
medium: "Configure and display the active namespace used to scope commands. Set, view, or list available namespaces for your session.",
|
|
45194
|
+
long: "Control which namespace subsequent operations target by default. Namespaces partition resources and configurations, ensuring commands affect only the intended area. Use 'show' to display the current selection, 'set' to switch contexts, and 'list' to enumerate accessible options. Once configured, the choice persists across commands until explicitly changed, eliminating repeated namespace flag usage."
|
|
45195
|
+
}
|
|
45196
|
+
}
|
|
45197
|
+
},
|
|
45198
|
+
"cloudstatus": {
|
|
45199
|
+
short: "Check infrastructure health and active incidents",
|
|
45200
|
+
medium: "Query service availability, component health, ongoing incidents, and scheduled maintenance windows across infrastructure regions.",
|
|
45201
|
+
long: "Display real-time operational state for infrastructure components and services. Track ongoing incidents with severity levels and resolution timelines. View upcoming maintenance windows affecting particular regions or deployments. Filter results by component type, severity, time range, or operational condition. Retrieve incident history and outage notifications. Commands support monitoring degraded performance indicators and uptime metrics useful for operations teams."
|
|
45202
|
+
},
|
|
45203
|
+
"completion": {
|
|
45204
|
+
short: "Generate tab-assist scripts for supported shells",
|
|
45205
|
+
medium: "Create shell scripts enabling tab-triggered suggestions for commands, subcommands, flags, and option values in bash, zsh, and fish.",
|
|
45206
|
+
long: "Output autocomplete functionality for your terminal environment. Bash, zsh, and fish are fully supported with context-aware prompts covering command names, nested subcommands, available flags, and valid argument values. Installation requires sourcing the generated content in your shell's configuration file (.bashrc, .zshrc, or config.fish). Execute the appropriate subcommand to produce the script, then follow shell-specific setup instructions to activate intelligent tab behavior."
|
|
45207
|
+
}
|
|
45208
|
+
}
|
|
45209
|
+
};
|
|
45210
|
+
function getCliDescriptions(cliName = "xcsh") {
|
|
45211
|
+
return generatedDescriptions.cli?.[cliName];
|
|
45212
|
+
}
|
|
45213
|
+
|
|
45169
45214
|
// src/branding/terminal.ts
|
|
45170
45215
|
function detectTerminalCapabilities() {
|
|
45171
45216
|
const termProgram = process.env.TERM_PROGRAM ?? "";
|
|
@@ -45309,8 +45354,8 @@ function getLogoModeFromEnv(envPrefix) {
|
|
|
45309
45354
|
var CLI_NAME = "xcsh";
|
|
45310
45355
|
var CLI_FULL_NAME = "F5 Distributed Cloud Shell";
|
|
45311
45356
|
function getVersion() {
|
|
45312
|
-
if ("6.
|
|
45313
|
-
return "6.
|
|
45357
|
+
if ("6.36.0") {
|
|
45358
|
+
return "6.36.0";
|
|
45314
45359
|
}
|
|
45315
45360
|
if (process.env.XCSH_VERSION) {
|
|
45316
45361
|
return process.env.XCSH_VERSION;
|
|
@@ -45318,6 +45363,10 @@ function getVersion() {
|
|
|
45318
45363
|
return "dev";
|
|
45319
45364
|
}
|
|
45320
45365
|
var CLI_VERSION = getVersion();
|
|
45366
|
+
var cliDescs = getCliDescriptions();
|
|
45367
|
+
var CLI_DESCRIPTION_SHORT = cliDescs?.short ?? "Navigate cloud services via interactive shell";
|
|
45368
|
+
var CLI_DESCRIPTION_MEDIUM = cliDescs?.medium ?? CLI_DESCRIPTION_SHORT;
|
|
45369
|
+
var CLI_DESCRIPTION_LONG = cliDescs?.long ?? CLI_DESCRIPTION_MEDIUM;
|
|
45321
45370
|
var CONFIG_FILE_NAME = ".xcshconfig";
|
|
45322
45371
|
var ENV_PREFIX = "F5XC";
|
|
45323
45372
|
var F5_LOGO = ` ________
|
|
@@ -46794,96 +46843,542 @@ function useHistory(options) {
|
|
|
46794
46843
|
// src/repl/hooks/useCompletion.ts
|
|
46795
46844
|
var import_react27 = __toESM(require_react(), 1);
|
|
46796
46845
|
|
|
46797
|
-
// src/
|
|
46798
|
-
var
|
|
46799
|
-
|
|
46800
|
-
|
|
46801
|
-
|
|
46802
|
-
|
|
46803
|
-
|
|
46804
|
-
|
|
46846
|
+
// src/config/envvars.ts
|
|
46847
|
+
var EnvVarRegistry = [
|
|
46848
|
+
{
|
|
46849
|
+
name: `${ENV_PREFIX}_API_URL`,
|
|
46850
|
+
description: "API endpoint URL",
|
|
46851
|
+
relatedFlag: "",
|
|
46852
|
+
required: true
|
|
46853
|
+
},
|
|
46854
|
+
{
|
|
46855
|
+
name: `${ENV_PREFIX}_API_TOKEN`,
|
|
46856
|
+
description: "API authentication token",
|
|
46857
|
+
relatedFlag: "",
|
|
46858
|
+
required: true
|
|
46859
|
+
},
|
|
46860
|
+
{
|
|
46861
|
+
name: `${ENV_PREFIX}_NAMESPACE`,
|
|
46862
|
+
description: "Default namespace",
|
|
46863
|
+
relatedFlag: "-ns"
|
|
46864
|
+
},
|
|
46865
|
+
{
|
|
46866
|
+
name: `${ENV_PREFIX}_OUTPUT_FORMAT`,
|
|
46867
|
+
description: "Output format (json, yaml, table)",
|
|
46868
|
+
relatedFlag: "-o"
|
|
46869
|
+
},
|
|
46870
|
+
{
|
|
46871
|
+
name: `${ENV_PREFIX}_LOGO`,
|
|
46872
|
+
description: "Logo display mode (auto, image, ascii, both, none)",
|
|
46873
|
+
relatedFlag: "--logo"
|
|
46874
|
+
},
|
|
46875
|
+
{
|
|
46876
|
+
name: "NO_COLOR",
|
|
46877
|
+
description: "Disable color output",
|
|
46878
|
+
relatedFlag: "--no-color"
|
|
46805
46879
|
}
|
|
46806
|
-
|
|
46807
|
-
|
|
46808
|
-
|
|
46809
|
-
|
|
46810
|
-
|
|
46880
|
+
];
|
|
46881
|
+
function formatEnvVarsSection() {
|
|
46882
|
+
const maxLen = Math.max(...EnvVarRegistry.map((e) => e.name.length));
|
|
46883
|
+
const lines = ["ENVIRONMENT VARIABLES"];
|
|
46884
|
+
for (const env3 of EnvVarRegistry) {
|
|
46885
|
+
const padding = " ".repeat(maxLen - env3.name.length + 3);
|
|
46886
|
+
const flagNote = env3.relatedFlag ? ` [${env3.relatedFlag}]` : "";
|
|
46887
|
+
lines.push(` ${env3.name}${padding}${env3.description}${flagNote}`);
|
|
46811
46888
|
}
|
|
46812
|
-
|
|
46813
|
-
|
|
46814
|
-
|
|
46815
|
-
|
|
46816
|
-
|
|
46889
|
+
return lines;
|
|
46890
|
+
}
|
|
46891
|
+
function formatConfigSection() {
|
|
46892
|
+
return [
|
|
46893
|
+
"CONFIGURATION",
|
|
46894
|
+
` Config file: ~/${CONFIG_FILE_NAME}`,
|
|
46895
|
+
" Priority: CLI flags > environment variables > config file > defaults",
|
|
46896
|
+
"",
|
|
46897
|
+
"DOCUMENTATION",
|
|
46898
|
+
` ${DOCS_URL}`
|
|
46899
|
+
];
|
|
46900
|
+
}
|
|
46901
|
+
|
|
46902
|
+
// src/repl/help.ts
|
|
46903
|
+
function wrapText2(text, width, indent) {
|
|
46904
|
+
const prefix = " ".repeat(indent);
|
|
46905
|
+
const words = text.split(/\s+/);
|
|
46906
|
+
const lines = [];
|
|
46907
|
+
let currentLine = prefix;
|
|
46908
|
+
for (const word of words) {
|
|
46909
|
+
if (currentLine.length + word.length + 1 > width && currentLine !== prefix) {
|
|
46910
|
+
lines.push(currentLine);
|
|
46911
|
+
currentLine = prefix + word;
|
|
46912
|
+
} else {
|
|
46913
|
+
currentLine += (currentLine === prefix ? "" : " ") + word;
|
|
46914
|
+
}
|
|
46817
46915
|
}
|
|
46818
|
-
|
|
46819
|
-
|
|
46820
|
-
*/
|
|
46821
|
-
list() {
|
|
46822
|
-
return Array.from(this.domains.keys());
|
|
46916
|
+
if (currentLine.trim()) {
|
|
46917
|
+
lines.push(currentLine);
|
|
46823
46918
|
}
|
|
46824
|
-
|
|
46825
|
-
|
|
46826
|
-
|
|
46827
|
-
|
|
46828
|
-
|
|
46919
|
+
return lines;
|
|
46920
|
+
}
|
|
46921
|
+
function formatRootHelp() {
|
|
46922
|
+
return [
|
|
46923
|
+
"",
|
|
46924
|
+
colorBoldWhite(`${CLI_NAME} - ${CLI_FULL_NAME} v${CLI_VERSION}`),
|
|
46925
|
+
"",
|
|
46926
|
+
"DESCRIPTION",
|
|
46927
|
+
...wrapText2(CLI_DESCRIPTION_LONG, 80, 2),
|
|
46928
|
+
"",
|
|
46929
|
+
"USAGE",
|
|
46930
|
+
` ${CLI_NAME} Enter interactive REPL mode`,
|
|
46931
|
+
` ${CLI_NAME} <domain> <action> Execute command non-interactively`,
|
|
46932
|
+
` ${CLI_NAME} help [topic] Show help for a topic`,
|
|
46933
|
+
"",
|
|
46934
|
+
"EXAMPLES",
|
|
46935
|
+
` ${CLI_NAME} tenant_and_identity list namespace List all namespaces`,
|
|
46936
|
+
` ${CLI_NAME} virtual get http_loadbalancer Get a specific load balancer`,
|
|
46937
|
+
` ${CLI_NAME} dns list List DNS zones`,
|
|
46938
|
+
` ${CLI_NAME} waf list -ns prod List WAF policies in prod`,
|
|
46939
|
+
` ${CLI_NAME} --interactive Force interactive REPL mode`,
|
|
46940
|
+
"",
|
|
46941
|
+
...formatDomainsSection(),
|
|
46942
|
+
"",
|
|
46943
|
+
...formatGlobalFlags(),
|
|
46944
|
+
"",
|
|
46945
|
+
...formatEnvVarsSection(),
|
|
46946
|
+
"",
|
|
46947
|
+
...formatConfigSection(),
|
|
46948
|
+
"",
|
|
46949
|
+
"NAVIGATION (Interactive Mode)",
|
|
46950
|
+
" <domain> Navigate into a domain (e.g., 'dns', 'lb')",
|
|
46951
|
+
" /domain Navigate directly to domain from anywhere",
|
|
46952
|
+
" .. Go up one level",
|
|
46953
|
+
" / Return to root",
|
|
46954
|
+
" context Show current navigation context",
|
|
46955
|
+
"",
|
|
46956
|
+
"BUILTINS",
|
|
46957
|
+
" help Show this help",
|
|
46958
|
+
" domains List all available domains",
|
|
46959
|
+
" clear Clear the screen",
|
|
46960
|
+
" history Show command history",
|
|
46961
|
+
" quit, exit Exit the shell",
|
|
46962
|
+
""
|
|
46963
|
+
];
|
|
46964
|
+
}
|
|
46965
|
+
function formatGlobalFlags() {
|
|
46966
|
+
return [
|
|
46967
|
+
"GLOBAL FLAGS",
|
|
46968
|
+
" -v, --version Show version number",
|
|
46969
|
+
" -h, --help Show this help",
|
|
46970
|
+
" -i, --interactive Force interactive mode",
|
|
46971
|
+
" --no-color Disable color output",
|
|
46972
|
+
" -o, --output <fmt> Output format (json, yaml, table)",
|
|
46973
|
+
" -ns, --namespace <ns> Target namespace"
|
|
46974
|
+
];
|
|
46975
|
+
}
|
|
46976
|
+
function formatEnvironmentVariables() {
|
|
46977
|
+
return formatEnvVarsSection();
|
|
46978
|
+
}
|
|
46979
|
+
function formatDomainHelp(domain) {
|
|
46980
|
+
const output = ["", colorBoldWhite(`${domain.displayName}`), ""];
|
|
46981
|
+
output.push(` ${domain.description}`);
|
|
46982
|
+
output.push("");
|
|
46983
|
+
if (domain.category || domain.complexity) {
|
|
46984
|
+
const meta = [];
|
|
46985
|
+
if (domain.category) meta.push(`Category: ${domain.category}`);
|
|
46986
|
+
if (domain.complexity) meta.push(`Complexity: ${domain.complexity}`);
|
|
46987
|
+
output.push(colorDim(` ${meta.join(" | ")}`));
|
|
46988
|
+
output.push("");
|
|
46829
46989
|
}
|
|
46830
|
-
|
|
46831
|
-
|
|
46832
|
-
|
|
46833
|
-
|
|
46834
|
-
|
|
46835
|
-
|
|
46836
|
-
|
|
46837
|
-
|
|
46838
|
-
|
|
46839
|
-
|
|
46840
|
-
|
|
46841
|
-
|
|
46842
|
-
|
|
46843
|
-
|
|
46844
|
-
|
|
46845
|
-
|
|
46846
|
-
|
|
46847
|
-
|
|
46848
|
-
}
|
|
46849
|
-
|
|
46850
|
-
|
|
46851
|
-
|
|
46852
|
-
|
|
46853
|
-
|
|
46854
|
-
|
|
46855
|
-
|
|
46856
|
-
|
|
46857
|
-
|
|
46858
|
-
|
|
46990
|
+
output.push("USAGE");
|
|
46991
|
+
output.push(` ${CLI_NAME} ${domain.name} <action> [options]`);
|
|
46992
|
+
output.push("");
|
|
46993
|
+
output.push("ACTIONS");
|
|
46994
|
+
const actionDescriptions2 = {
|
|
46995
|
+
list: "List resources",
|
|
46996
|
+
get: "Get a specific resource by name",
|
|
46997
|
+
create: "Create a new resource",
|
|
46998
|
+
delete: "Delete a resource",
|
|
46999
|
+
replace: "Replace a resource configuration",
|
|
47000
|
+
apply: "Apply configuration from file",
|
|
47001
|
+
status: "Get resource status",
|
|
47002
|
+
patch: "Patch a resource",
|
|
47003
|
+
"add-labels": "Add labels to a resource",
|
|
47004
|
+
"remove-labels": "Remove labels from a resource"
|
|
47005
|
+
};
|
|
47006
|
+
for (const action of validActions) {
|
|
47007
|
+
const desc = actionDescriptions2[action] ?? action;
|
|
47008
|
+
output.push(` ${action.padEnd(16)} ${desc}`);
|
|
47009
|
+
}
|
|
47010
|
+
output.push("");
|
|
47011
|
+
output.push("EXAMPLES");
|
|
47012
|
+
output.push(` ${CLI_NAME} ${domain.name} list`);
|
|
47013
|
+
output.push(` ${CLI_NAME} ${domain.name} get my-resource`);
|
|
47014
|
+
output.push(
|
|
47015
|
+
` ${CLI_NAME} ${domain.name} create my-resource -f config.yaml`
|
|
47016
|
+
);
|
|
47017
|
+
output.push(` ${CLI_NAME} ${domain.name} delete my-resource`);
|
|
47018
|
+
output.push("");
|
|
47019
|
+
if (domain.useCases && domain.useCases.length > 0) {
|
|
47020
|
+
output.push("USE CASES");
|
|
47021
|
+
for (const useCase of domain.useCases.slice(0, 5)) {
|
|
47022
|
+
output.push(` - ${useCase}`);
|
|
46859
47023
|
}
|
|
46860
|
-
|
|
46861
|
-
|
|
46862
|
-
|
|
46863
|
-
|
|
46864
|
-
|
|
46865
|
-
|
|
46866
|
-
|
|
46867
|
-
|
|
46868
|
-
|
|
46869
|
-
|
|
46870
|
-
|
|
46871
|
-
|
|
46872
|
-
|
|
46873
|
-
|
|
46874
|
-
|
|
46875
|
-
|
|
46876
|
-
|
|
46877
|
-
|
|
46878
|
-
|
|
46879
|
-
|
|
46880
|
-
|
|
46881
|
-
|
|
46882
|
-
|
|
46883
|
-
|
|
46884
|
-
|
|
46885
|
-
|
|
46886
|
-
|
|
47024
|
+
output.push("");
|
|
47025
|
+
}
|
|
47026
|
+
if (domain.relatedDomains && domain.relatedDomains.length > 0) {
|
|
47027
|
+
output.push("RELATED DOMAINS");
|
|
47028
|
+
output.push(` ${domain.relatedDomains.join(", ")}`);
|
|
47029
|
+
output.push("");
|
|
47030
|
+
}
|
|
47031
|
+
if (domain.aliases && domain.aliases.length > 0) {
|
|
47032
|
+
output.push("ALIASES");
|
|
47033
|
+
output.push(` ${domain.aliases.join(", ")}`);
|
|
47034
|
+
output.push("");
|
|
47035
|
+
}
|
|
47036
|
+
output.push(colorDim(`For global options, run: ${CLI_NAME} --help`));
|
|
47037
|
+
output.push("");
|
|
47038
|
+
return output;
|
|
47039
|
+
}
|
|
47040
|
+
function formatActionHelp(domainName, action) {
|
|
47041
|
+
const domain = getDomainInfo(domainName);
|
|
47042
|
+
const displayDomain = domain?.displayName ?? domainName;
|
|
47043
|
+
const actionDescriptions2 = {
|
|
47044
|
+
list: {
|
|
47045
|
+
desc: "List all resources in the namespace",
|
|
47046
|
+
usage: `${CLI_NAME} ${domainName} list [--limit N] [--label key=value]`
|
|
47047
|
+
},
|
|
47048
|
+
get: {
|
|
47049
|
+
desc: "Get a specific resource by name",
|
|
47050
|
+
usage: `${CLI_NAME} ${domainName} get <name> [-o json|yaml|table]`
|
|
47051
|
+
},
|
|
47052
|
+
create: {
|
|
47053
|
+
desc: "Create a new resource",
|
|
47054
|
+
usage: `${CLI_NAME} ${domainName} create <name> -f <file.yaml>`
|
|
47055
|
+
},
|
|
47056
|
+
delete: {
|
|
47057
|
+
desc: "Delete a resource by name",
|
|
47058
|
+
usage: `${CLI_NAME} ${domainName} delete <name>`
|
|
47059
|
+
},
|
|
47060
|
+
replace: {
|
|
47061
|
+
desc: "Replace an existing resource configuration",
|
|
47062
|
+
usage: `${CLI_NAME} ${domainName} replace <name> -f <file.yaml>`
|
|
47063
|
+
},
|
|
47064
|
+
apply: {
|
|
47065
|
+
desc: "Apply configuration from a file (create or update)",
|
|
47066
|
+
usage: `${CLI_NAME} ${domainName} apply -f <file.yaml>`
|
|
47067
|
+
},
|
|
47068
|
+
status: {
|
|
47069
|
+
desc: "Get the current status of a resource",
|
|
47070
|
+
usage: `${CLI_NAME} ${domainName} status <name>`
|
|
47071
|
+
},
|
|
47072
|
+
patch: {
|
|
47073
|
+
desc: "Patch specific fields of a resource",
|
|
47074
|
+
usage: `${CLI_NAME} ${domainName} patch <name> -f <patch.yaml>`
|
|
47075
|
+
},
|
|
47076
|
+
"add-labels": {
|
|
47077
|
+
desc: "Add labels to a resource",
|
|
47078
|
+
usage: `${CLI_NAME} ${domainName} add-labels <name> key=value`
|
|
47079
|
+
},
|
|
47080
|
+
"remove-labels": {
|
|
47081
|
+
desc: "Remove labels from a resource",
|
|
47082
|
+
usage: `${CLI_NAME} ${domainName} remove-labels <name> key`
|
|
47083
|
+
}
|
|
47084
|
+
};
|
|
47085
|
+
const actionInfo = actionDescriptions2[action] ?? {
|
|
47086
|
+
desc: `Execute ${action} operation`,
|
|
47087
|
+
usage: `${CLI_NAME} ${domainName} ${action} [options]`
|
|
47088
|
+
};
|
|
47089
|
+
return [
|
|
47090
|
+
"",
|
|
47091
|
+
colorBoldWhite(`${displayDomain} - ${action}`),
|
|
47092
|
+
"",
|
|
47093
|
+
` ${actionInfo.desc}`,
|
|
47094
|
+
"",
|
|
47095
|
+
"USAGE",
|
|
47096
|
+
` ${actionInfo.usage}`,
|
|
47097
|
+
"",
|
|
47098
|
+
"OPTIONS",
|
|
47099
|
+
" -n, --name <name> Resource name",
|
|
47100
|
+
" -ns, --namespace <ns> Target namespace",
|
|
47101
|
+
" -o, --output <fmt> Output format (json, yaml, table)",
|
|
47102
|
+
" -f, --file <path> Configuration file",
|
|
47103
|
+
"",
|
|
47104
|
+
colorDim(`For domain help, run: ${CLI_NAME} ${domainName} --help`),
|
|
47105
|
+
""
|
|
47106
|
+
];
|
|
47107
|
+
}
|
|
47108
|
+
function formatTopicHelp(topic) {
|
|
47109
|
+
const lowerTopic = topic.toLowerCase();
|
|
47110
|
+
const domainInfo = getDomainInfo(lowerTopic);
|
|
47111
|
+
if (domainInfo) {
|
|
47112
|
+
return formatDomainHelp(domainInfo);
|
|
47113
|
+
}
|
|
47114
|
+
switch (lowerTopic) {
|
|
47115
|
+
case "domains":
|
|
47116
|
+
return formatDomainsHelp();
|
|
47117
|
+
case "actions":
|
|
47118
|
+
return formatActionsHelp();
|
|
47119
|
+
case "navigation":
|
|
47120
|
+
case "nav":
|
|
47121
|
+
return formatNavigationHelp();
|
|
47122
|
+
case "env":
|
|
47123
|
+
case "environment":
|
|
47124
|
+
return ["", ...formatEnvironmentVariables(), ""];
|
|
47125
|
+
case "flags":
|
|
47126
|
+
return ["", ...formatGlobalFlags(), ""];
|
|
47127
|
+
default:
|
|
47128
|
+
return [
|
|
47129
|
+
"",
|
|
47130
|
+
`Unknown help topic: ${topic}`,
|
|
47131
|
+
"",
|
|
47132
|
+
"Available topics:",
|
|
47133
|
+
" domains List all available domains",
|
|
47134
|
+
" actions List available actions",
|
|
47135
|
+
" navigation Navigation commands",
|
|
47136
|
+
" env Environment variables",
|
|
47137
|
+
" flags Global flags",
|
|
47138
|
+
" <domain> Help for a specific domain (e.g., 'help dns')",
|
|
47139
|
+
""
|
|
47140
|
+
];
|
|
47141
|
+
}
|
|
47142
|
+
}
|
|
47143
|
+
function formatDomainsHelp() {
|
|
47144
|
+
const output = ["", colorBoldWhite("Available Domains"), ""];
|
|
47145
|
+
const categories = /* @__PURE__ */ new Map();
|
|
47146
|
+
for (const domain of domainRegistry.values()) {
|
|
47147
|
+
const category = domain.category ?? "Other";
|
|
47148
|
+
if (!categories.has(category)) {
|
|
47149
|
+
categories.set(category, []);
|
|
47150
|
+
}
|
|
47151
|
+
categories.get(category)?.push(domain);
|
|
47152
|
+
}
|
|
47153
|
+
const sortedCategories = Array.from(categories.keys()).sort();
|
|
47154
|
+
for (const category of sortedCategories) {
|
|
47155
|
+
const domains = categories.get(category) ?? [];
|
|
47156
|
+
output.push(colorBoldWhite(` ${category}`));
|
|
47157
|
+
for (const domain of domains.sort(
|
|
47158
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
47159
|
+
)) {
|
|
47160
|
+
const aliases = domain.aliases.length > 0 ? colorDim(` (${domain.aliases.join(", ")})`) : "";
|
|
47161
|
+
output.push(
|
|
47162
|
+
` ${domain.name.padEnd(24)} ${domain.descriptionShort}`
|
|
47163
|
+
);
|
|
47164
|
+
if (aliases) {
|
|
47165
|
+
output.push(` ${"".padEnd(24)} Aliases:${aliases}`);
|
|
47166
|
+
}
|
|
47167
|
+
}
|
|
47168
|
+
output.push("");
|
|
47169
|
+
}
|
|
47170
|
+
return output;
|
|
47171
|
+
}
|
|
47172
|
+
function formatActionsHelp() {
|
|
47173
|
+
return [
|
|
47174
|
+
"",
|
|
47175
|
+
colorBoldWhite("Available Actions"),
|
|
47176
|
+
"",
|
|
47177
|
+
" list List all resources in the namespace",
|
|
47178
|
+
" get Get a specific resource by name",
|
|
47179
|
+
" create Create a new resource from a file",
|
|
47180
|
+
" delete Delete a resource by name",
|
|
47181
|
+
" replace Replace a resource configuration",
|
|
47182
|
+
" apply Apply configuration (create or update)",
|
|
47183
|
+
" status Get resource status",
|
|
47184
|
+
" patch Patch specific fields of a resource",
|
|
47185
|
+
" add-labels Add labels to a resource",
|
|
47186
|
+
" remove-labels Remove labels from a resource",
|
|
47187
|
+
"",
|
|
47188
|
+
"USAGE",
|
|
47189
|
+
` ${CLI_NAME} <domain> <action> [options]`,
|
|
47190
|
+
"",
|
|
47191
|
+
"EXAMPLES",
|
|
47192
|
+
` ${CLI_NAME} dns list`,
|
|
47193
|
+
` ${CLI_NAME} lb get my-loadbalancer`,
|
|
47194
|
+
` ${CLI_NAME} waf create my-policy -f policy.yaml`,
|
|
47195
|
+
""
|
|
47196
|
+
];
|
|
47197
|
+
}
|
|
47198
|
+
function formatNavigationHelp() {
|
|
47199
|
+
return [
|
|
47200
|
+
"",
|
|
47201
|
+
colorBoldWhite("Navigation Commands"),
|
|
47202
|
+
"",
|
|
47203
|
+
" <domain> Navigate into a domain context",
|
|
47204
|
+
" /<domain> Navigate directly to domain from anywhere",
|
|
47205
|
+
" .. Go up one level in context",
|
|
47206
|
+
" / Return to root context",
|
|
47207
|
+
" back Go up one level (same as ..)",
|
|
47208
|
+
" root Return to root (same as /)",
|
|
47209
|
+
"",
|
|
47210
|
+
"CONTEXT DISPLAY",
|
|
47211
|
+
" context Show current navigation context",
|
|
47212
|
+
" ctx Alias for context",
|
|
47213
|
+
"",
|
|
47214
|
+
"EXAMPLES",
|
|
47215
|
+
" xcsh> dns # Enter dns domain",
|
|
47216
|
+
" dns> list # Execute list in dns context",
|
|
47217
|
+
" dns> .. # Return to root",
|
|
47218
|
+
" xcsh> /waf # Jump directly to waf",
|
|
47219
|
+
" waf> /dns # Jump from waf to dns",
|
|
47220
|
+
""
|
|
47221
|
+
];
|
|
47222
|
+
}
|
|
47223
|
+
function formatDomainsSection() {
|
|
47224
|
+
const output = ["DOMAINS"];
|
|
47225
|
+
const domains = Array.from(domainRegistry.values()).sort(
|
|
47226
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
47227
|
+
);
|
|
47228
|
+
const maxNameLen = Math.max(...domains.map((d) => d.name.length));
|
|
47229
|
+
for (const domain of domains) {
|
|
47230
|
+
const padding = " ".repeat(maxNameLen - domain.name.length + 2);
|
|
47231
|
+
output.push(` ${domain.name}${padding}${domain.descriptionShort}`);
|
|
47232
|
+
}
|
|
47233
|
+
return output;
|
|
47234
|
+
}
|
|
47235
|
+
function formatCustomDomainHelp(domain) {
|
|
47236
|
+
const output = ["", colorBoldWhite(domain.name), ""];
|
|
47237
|
+
output.push("DESCRIPTION");
|
|
47238
|
+
output.push(...wrapText2(domain.description, 80, 2));
|
|
47239
|
+
output.push("");
|
|
47240
|
+
output.push("USAGE");
|
|
47241
|
+
output.push(` ${CLI_NAME} ${domain.name} <command> [options]`);
|
|
47242
|
+
output.push("");
|
|
47243
|
+
if (domain.subcommands.size > 0) {
|
|
47244
|
+
output.push("SUBCOMMANDS");
|
|
47245
|
+
for (const [name, group] of domain.subcommands) {
|
|
47246
|
+
output.push(` ${name.padEnd(16)} ${group.descriptionShort}`);
|
|
47247
|
+
}
|
|
47248
|
+
output.push("");
|
|
47249
|
+
}
|
|
47250
|
+
if (domain.commands.size > 0) {
|
|
47251
|
+
output.push("COMMANDS");
|
|
47252
|
+
for (const [name, cmd] of domain.commands) {
|
|
47253
|
+
output.push(` ${name.padEnd(16)} ${cmd.descriptionShort}`);
|
|
47254
|
+
}
|
|
47255
|
+
output.push("");
|
|
47256
|
+
}
|
|
47257
|
+
output.push(colorDim(`For global options, run: ${CLI_NAME} --help`));
|
|
47258
|
+
output.push("");
|
|
47259
|
+
return output;
|
|
47260
|
+
}
|
|
47261
|
+
function formatSubcommandHelp(domainName, subcommand) {
|
|
47262
|
+
const output = [
|
|
47263
|
+
"",
|
|
47264
|
+
colorBoldWhite(`${domainName} ${subcommand.name}`),
|
|
47265
|
+
""
|
|
47266
|
+
];
|
|
47267
|
+
output.push("DESCRIPTION");
|
|
47268
|
+
output.push(...wrapText2(subcommand.description, 80, 2));
|
|
47269
|
+
output.push("");
|
|
47270
|
+
output.push("USAGE");
|
|
47271
|
+
output.push(
|
|
47272
|
+
` ${CLI_NAME} ${domainName} ${subcommand.name} <command> [options]`
|
|
47273
|
+
);
|
|
47274
|
+
output.push("");
|
|
47275
|
+
if (subcommand.commands.size > 0) {
|
|
47276
|
+
output.push("COMMANDS");
|
|
47277
|
+
for (const [name, cmd] of subcommand.commands) {
|
|
47278
|
+
const usage = cmd.usage ? ` ${cmd.usage}` : "";
|
|
47279
|
+
output.push(
|
|
47280
|
+
` ${name}${usage.padEnd(16 - name.length)} ${cmd.descriptionShort}`
|
|
47281
|
+
);
|
|
47282
|
+
}
|
|
47283
|
+
output.push("");
|
|
47284
|
+
}
|
|
47285
|
+
output.push(
|
|
47286
|
+
colorDim(`For domain help, run: ${CLI_NAME} ${domainName} --help`)
|
|
47287
|
+
);
|
|
47288
|
+
output.push("");
|
|
47289
|
+
return output;
|
|
47290
|
+
}
|
|
47291
|
+
|
|
47292
|
+
// src/domains/registry.ts
|
|
47293
|
+
var DomainRegistry = class {
|
|
47294
|
+
domains = /* @__PURE__ */ new Map();
|
|
47295
|
+
/**
|
|
47296
|
+
* Register a custom domain
|
|
47297
|
+
*/
|
|
47298
|
+
register(domain) {
|
|
47299
|
+
this.domains.set(domain.name, domain);
|
|
47300
|
+
}
|
|
47301
|
+
/**
|
|
47302
|
+
* Check if a domain is registered
|
|
47303
|
+
*/
|
|
47304
|
+
has(name) {
|
|
47305
|
+
return this.domains.has(name);
|
|
47306
|
+
}
|
|
47307
|
+
/**
|
|
47308
|
+
* Get a domain by name
|
|
47309
|
+
*/
|
|
47310
|
+
get(name) {
|
|
47311
|
+
return this.domains.get(name);
|
|
47312
|
+
}
|
|
47313
|
+
/**
|
|
47314
|
+
* Get all registered domain names
|
|
47315
|
+
*/
|
|
47316
|
+
list() {
|
|
47317
|
+
return Array.from(this.domains.keys());
|
|
47318
|
+
}
|
|
47319
|
+
/**
|
|
47320
|
+
* Get all domains
|
|
47321
|
+
*/
|
|
47322
|
+
all() {
|
|
47323
|
+
return Array.from(this.domains.values());
|
|
47324
|
+
}
|
|
47325
|
+
/**
|
|
47326
|
+
* Execute a command within a domain
|
|
47327
|
+
* Handles routing through subcommand groups
|
|
47328
|
+
*
|
|
47329
|
+
* @param domainName - Name of the domain (e.g., "login")
|
|
47330
|
+
* @param args - Command arguments (e.g., ["profile", "list"])
|
|
47331
|
+
* @param session - REPL session
|
|
47332
|
+
*/
|
|
47333
|
+
async execute(domainName, args, session) {
|
|
47334
|
+
const domain = this.domains.get(domainName);
|
|
47335
|
+
if (!domain) {
|
|
47336
|
+
return {
|
|
47337
|
+
output: [`Unknown domain: ${domainName}`],
|
|
47338
|
+
shouldExit: false,
|
|
47339
|
+
shouldClear: false,
|
|
47340
|
+
contextChanged: false,
|
|
47341
|
+
error: "Unknown domain"
|
|
47342
|
+
};
|
|
47343
|
+
}
|
|
47344
|
+
if (args.length === 0) {
|
|
47345
|
+
if (domain.defaultCommand) {
|
|
47346
|
+
return domain.defaultCommand.execute([], session);
|
|
47347
|
+
}
|
|
47348
|
+
return this.showDomainHelp(domain);
|
|
47349
|
+
}
|
|
47350
|
+
const firstArg = args[0]?.toLowerCase() ?? "";
|
|
47351
|
+
const restArgs = args.slice(1);
|
|
47352
|
+
if (firstArg === "--help" || firstArg === "-h" || firstArg === "help") {
|
|
47353
|
+
return this.showDomainHelp(domain);
|
|
47354
|
+
}
|
|
47355
|
+
const subgroup = domain.subcommands.get(firstArg);
|
|
47356
|
+
if (subgroup) {
|
|
47357
|
+
if (restArgs.length === 0) {
|
|
47358
|
+
if (subgroup.defaultCommand) {
|
|
47359
|
+
return subgroup.defaultCommand.execute([], session);
|
|
47360
|
+
}
|
|
47361
|
+
return this.showSubcommandHelp(domain, subgroup);
|
|
47362
|
+
}
|
|
47363
|
+
const cmdName = restArgs[0]?.toLowerCase() ?? "";
|
|
47364
|
+
if (cmdName === "--help" || cmdName === "-h" || cmdName === "help") {
|
|
47365
|
+
return this.showSubcommandHelp(domain, subgroup);
|
|
47366
|
+
}
|
|
47367
|
+
const cmdArgs = restArgs.slice(1);
|
|
47368
|
+
const cmd2 = subgroup.commands.get(cmdName);
|
|
47369
|
+
if (cmd2) {
|
|
47370
|
+
return cmd2.execute(cmdArgs, session);
|
|
47371
|
+
}
|
|
47372
|
+
for (const [, command] of subgroup.commands) {
|
|
47373
|
+
if (command.aliases?.includes(cmdName)) {
|
|
47374
|
+
return command.execute(cmdArgs, session);
|
|
47375
|
+
}
|
|
47376
|
+
}
|
|
47377
|
+
return {
|
|
47378
|
+
output: [
|
|
47379
|
+
`Unknown command: ${domainName} ${firstArg} ${cmdName}`,
|
|
47380
|
+
``,
|
|
47381
|
+
`Run '${domainName} ${firstArg}' for available commands.`
|
|
46887
47382
|
],
|
|
46888
47383
|
shouldExit: false,
|
|
46889
47384
|
shouldClear: false,
|
|
@@ -46975,45 +47470,24 @@ var DomainRegistry = class {
|
|
|
46975
47470
|
return suggestions;
|
|
46976
47471
|
}
|
|
46977
47472
|
/**
|
|
46978
|
-
* Show help for a domain
|
|
47473
|
+
* Show help for a domain using the unified help formatter.
|
|
47474
|
+
* This ensures consistent professional formatting across all domains.
|
|
46979
47475
|
*/
|
|
46980
47476
|
showDomainHelp(domain) {
|
|
46981
|
-
const output = [`${domain.name} - ${domain.description}`, ``];
|
|
46982
|
-
if (domain.subcommands.size > 0) {
|
|
46983
|
-
output.push(`Subcommands:`);
|
|
46984
|
-
for (const [name, group] of domain.subcommands) {
|
|
46985
|
-
output.push(` ${name} ${group.description}`);
|
|
46986
|
-
}
|
|
46987
|
-
output.push(``);
|
|
46988
|
-
}
|
|
46989
|
-
if (domain.commands.size > 0) {
|
|
46990
|
-
output.push(`Commands:`);
|
|
46991
|
-
for (const [name, cmd] of domain.commands) {
|
|
46992
|
-
output.push(` ${name} ${cmd.description}`);
|
|
46993
|
-
}
|
|
46994
|
-
}
|
|
46995
47477
|
return {
|
|
46996
|
-
output,
|
|
47478
|
+
output: formatCustomDomainHelp(domain),
|
|
46997
47479
|
shouldExit: false,
|
|
46998
47480
|
shouldClear: false,
|
|
46999
47481
|
contextChanged: false
|
|
47000
47482
|
};
|
|
47001
47483
|
}
|
|
47002
47484
|
/**
|
|
47003
|
-
* Show help for a subcommand group
|
|
47485
|
+
* Show help for a subcommand group using the unified help formatter.
|
|
47486
|
+
* This ensures consistent professional formatting across all subcommands.
|
|
47004
47487
|
*/
|
|
47005
47488
|
showSubcommandHelp(domain, subgroup) {
|
|
47006
|
-
const output = [
|
|
47007
|
-
`${domain.name} ${subgroup.name} - ${subgroup.description}`,
|
|
47008
|
-
``,
|
|
47009
|
-
`Commands:`
|
|
47010
|
-
];
|
|
47011
|
-
for (const [name, cmd] of subgroup.commands) {
|
|
47012
|
-
const usage = cmd.usage ? ` ${cmd.usage}` : "";
|
|
47013
|
-
output.push(` ${name}${usage} ${cmd.description}`);
|
|
47014
|
-
}
|
|
47015
47489
|
return {
|
|
47016
|
-
output,
|
|
47490
|
+
output: formatSubcommandHelp(domain.name, subgroup),
|
|
47017
47491
|
shouldExit: false,
|
|
47018
47492
|
shouldClear: false,
|
|
47019
47493
|
contextChanged: false
|
|
@@ -47495,75 +47969,19 @@ var listCommand2 = {
|
|
|
47495
47969
|
const message = error instanceof Error ? error.message : String(error);
|
|
47496
47970
|
return errorResult(`Failed to list namespaces: ${message}`);
|
|
47497
47971
|
}
|
|
47498
|
-
}
|
|
47499
|
-
};
|
|
47500
|
-
var contextSubcommands = {
|
|
47501
|
-
name: "context",
|
|
47502
|
-
description: "Manage default namespace context for scoping operations. Set, display, and list namespaces to control which namespace is used when no explicit namespace is specified in commands.",
|
|
47503
|
-
descriptionShort: "Manage default namespace context",
|
|
47504
|
-
descriptionMedium: "Set, display, and list namespaces for scoping operations without explicit namespace flags.",
|
|
47505
|
-
commands: /* @__PURE__ */ new Map([
|
|
47506
|
-
["show", showCommand2],
|
|
47507
|
-
["set", setCommand],
|
|
47508
|
-
["list", listCommand2]
|
|
47509
|
-
])
|
|
47510
|
-
};
|
|
47511
|
-
|
|
47512
|
-
// src/config/envvars.ts
|
|
47513
|
-
var EnvVarRegistry = [
|
|
47514
|
-
{
|
|
47515
|
-
name: `${ENV_PREFIX}_API_URL`,
|
|
47516
|
-
description: "API endpoint URL",
|
|
47517
|
-
relatedFlag: "",
|
|
47518
|
-
required: true
|
|
47519
|
-
},
|
|
47520
|
-
{
|
|
47521
|
-
name: `${ENV_PREFIX}_API_TOKEN`,
|
|
47522
|
-
description: "API authentication token",
|
|
47523
|
-
relatedFlag: "",
|
|
47524
|
-
required: true
|
|
47525
|
-
},
|
|
47526
|
-
{
|
|
47527
|
-
name: `${ENV_PREFIX}_NAMESPACE`,
|
|
47528
|
-
description: "Default namespace",
|
|
47529
|
-
relatedFlag: "-ns"
|
|
47530
|
-
},
|
|
47531
|
-
{
|
|
47532
|
-
name: `${ENV_PREFIX}_OUTPUT_FORMAT`,
|
|
47533
|
-
description: "Output format (json, yaml, table)",
|
|
47534
|
-
relatedFlag: "-o"
|
|
47535
|
-
},
|
|
47536
|
-
{
|
|
47537
|
-
name: `${ENV_PREFIX}_LOGO`,
|
|
47538
|
-
description: "Logo display mode (auto, image, ascii, both, none)",
|
|
47539
|
-
relatedFlag: "--logo"
|
|
47540
|
-
},
|
|
47541
|
-
{
|
|
47542
|
-
name: "NO_COLOR",
|
|
47543
|
-
description: "Disable color output",
|
|
47544
|
-
relatedFlag: "--no-color"
|
|
47545
|
-
}
|
|
47546
|
-
];
|
|
47547
|
-
function formatEnvVarsSection() {
|
|
47548
|
-
const maxLen = Math.max(...EnvVarRegistry.map((e) => e.name.length));
|
|
47549
|
-
const lines = ["ENVIRONMENT VARIABLES"];
|
|
47550
|
-
for (const env3 of EnvVarRegistry) {
|
|
47551
|
-
const padding = " ".repeat(maxLen - env3.name.length + 3);
|
|
47552
|
-
const flagNote = env3.relatedFlag ? ` [${env3.relatedFlag}]` : "";
|
|
47553
|
-
lines.push(` ${env3.name}${padding}${env3.description}${flagNote}`);
|
|
47554
|
-
}
|
|
47555
|
-
return lines;
|
|
47556
|
-
}
|
|
47557
|
-
function formatConfigSection() {
|
|
47558
|
-
return [
|
|
47559
|
-
"CONFIGURATION",
|
|
47560
|
-
` Config file: ~/${CONFIG_FILE_NAME}`,
|
|
47561
|
-
" Priority: CLI flags > environment variables > config file > defaults",
|
|
47562
|
-
"",
|
|
47563
|
-
"DOCUMENTATION",
|
|
47564
|
-
` ${DOCS_URL}`
|
|
47565
|
-
];
|
|
47566
|
-
}
|
|
47972
|
+
}
|
|
47973
|
+
};
|
|
47974
|
+
var contextSubcommands = {
|
|
47975
|
+
name: "context",
|
|
47976
|
+
description: "Manage default namespace context for scoping operations. Set, display, and list namespaces to control which namespace is used when no explicit namespace is specified in commands.",
|
|
47977
|
+
descriptionShort: "Manage default namespace context",
|
|
47978
|
+
descriptionMedium: "Set, display, and list namespaces for scoping operations without explicit namespace flags.",
|
|
47979
|
+
commands: /* @__PURE__ */ new Map([
|
|
47980
|
+
["show", showCommand2],
|
|
47981
|
+
["set", setCommand],
|
|
47982
|
+
["list", listCommand2]
|
|
47983
|
+
])
|
|
47984
|
+
};
|
|
47567
47985
|
|
|
47568
47986
|
// src/config/settings.ts
|
|
47569
47987
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
@@ -50477,567 +50895,251 @@ function useCompletion(options) {
|
|
|
50477
50895
|
setSuggestions(newSuggestions);
|
|
50478
50896
|
setSelectedIndex(0);
|
|
50479
50897
|
}
|
|
50480
|
-
},
|
|
50481
|
-
[completer, isShowing, hide]
|
|
50482
|
-
);
|
|
50483
|
-
const navigateUp = (0, import_react27.useCallback)(() => {
|
|
50484
|
-
if (!isShowing || suggestions.length === 0) return;
|
|
50485
|
-
setSelectedIndex(
|
|
50486
|
-
(current) => current > 0 ? current - 1 : suggestions.length - 1
|
|
50487
|
-
);
|
|
50488
|
-
}, [isShowing, suggestions.length]);
|
|
50489
|
-
const navigateDown = (0, import_react27.useCallback)(() => {
|
|
50490
|
-
if (!isShowing || suggestions.length === 0) return;
|
|
50491
|
-
setSelectedIndex(
|
|
50492
|
-
(current) => current < suggestions.length - 1 ? current + 1 : 0
|
|
50493
|
-
);
|
|
50494
|
-
}, [isShowing, suggestions.length]);
|
|
50495
|
-
const selectCurrent = (0, import_react27.useCallback)(() => {
|
|
50496
|
-
if (!isShowing || suggestions.length === 0) return null;
|
|
50497
|
-
const selected = suggestions.at(selectedIndex);
|
|
50498
|
-
hide();
|
|
50499
|
-
return selected ?? null;
|
|
50500
|
-
}, [isShowing, suggestions, selectedIndex, hide]);
|
|
50501
|
-
return {
|
|
50502
|
-
suggestions,
|
|
50503
|
-
selectedIndex,
|
|
50504
|
-
isShowing,
|
|
50505
|
-
triggerCompletion,
|
|
50506
|
-
navigateUp,
|
|
50507
|
-
navigateDown,
|
|
50508
|
-
selectCurrent,
|
|
50509
|
-
hide,
|
|
50510
|
-
filterSuggestions
|
|
50511
|
-
};
|
|
50512
|
-
}
|
|
50513
|
-
|
|
50514
|
-
// src/output/formatter.ts
|
|
50515
|
-
var import_yaml3 = __toESM(require_dist(), 1);
|
|
50516
|
-
function formatOutput(data, format = "yaml") {
|
|
50517
|
-
if (format === "none") {
|
|
50518
|
-
return "";
|
|
50519
|
-
}
|
|
50520
|
-
switch (format) {
|
|
50521
|
-
case "json":
|
|
50522
|
-
return formatJSON(data);
|
|
50523
|
-
case "yaml":
|
|
50524
|
-
return formatYAML(data);
|
|
50525
|
-
case "table":
|
|
50526
|
-
case "text":
|
|
50527
|
-
return formatTable(data);
|
|
50528
|
-
case "tsv":
|
|
50529
|
-
return formatTSV(data);
|
|
50530
|
-
default:
|
|
50531
|
-
return formatYAML(data);
|
|
50532
|
-
}
|
|
50533
|
-
}
|
|
50534
|
-
function formatJSON(data) {
|
|
50535
|
-
return JSON.stringify(data, null, 2);
|
|
50536
|
-
}
|
|
50537
|
-
function formatYAML(data) {
|
|
50538
|
-
return import_yaml3.default.stringify(data, { indent: 2 });
|
|
50539
|
-
}
|
|
50540
|
-
function extractItems(data) {
|
|
50541
|
-
if (data && typeof data === "object" && "items" in data) {
|
|
50542
|
-
const items = data.items;
|
|
50543
|
-
if (Array.isArray(items)) {
|
|
50544
|
-
return items.filter(
|
|
50545
|
-
(item) => item !== null && typeof item === "object"
|
|
50546
|
-
);
|
|
50547
|
-
}
|
|
50548
|
-
}
|
|
50549
|
-
if (Array.isArray(data)) {
|
|
50550
|
-
return data.filter(
|
|
50551
|
-
(item) => item !== null && typeof item === "object"
|
|
50552
|
-
);
|
|
50553
|
-
}
|
|
50554
|
-
if (data && typeof data === "object") {
|
|
50555
|
-
return [data];
|
|
50556
|
-
}
|
|
50557
|
-
return [];
|
|
50558
|
-
}
|
|
50559
|
-
function getStringField(obj, key) {
|
|
50560
|
-
const value = obj[key];
|
|
50561
|
-
if (typeof value === "string") {
|
|
50562
|
-
return value;
|
|
50563
|
-
}
|
|
50564
|
-
if (value !== null && value !== void 0) {
|
|
50565
|
-
return String(value);
|
|
50566
|
-
}
|
|
50567
|
-
return "";
|
|
50568
|
-
}
|
|
50569
|
-
function formatLabels(obj) {
|
|
50570
|
-
const labels = obj["labels"];
|
|
50571
|
-
if (!labels || typeof labels !== "object") {
|
|
50572
|
-
return "";
|
|
50573
|
-
}
|
|
50574
|
-
const labelMap = labels;
|
|
50575
|
-
const entries = Object.entries(labelMap).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}:${v}`);
|
|
50576
|
-
if (entries.length === 0) {
|
|
50577
|
-
return "";
|
|
50578
|
-
}
|
|
50579
|
-
return `map[${entries.join(" ")}]`;
|
|
50580
|
-
}
|
|
50581
|
-
function wrapText2(text, maxWidth) {
|
|
50582
|
-
if (text.length <= maxWidth) {
|
|
50583
|
-
return [text];
|
|
50584
|
-
}
|
|
50585
|
-
const lines = [];
|
|
50586
|
-
let remaining = text;
|
|
50587
|
-
while (remaining.length > 0) {
|
|
50588
|
-
if (remaining.length <= maxWidth) {
|
|
50589
|
-
lines.push(remaining);
|
|
50590
|
-
break;
|
|
50591
|
-
}
|
|
50592
|
-
let breakPoint = maxWidth;
|
|
50593
|
-
for (let i = maxWidth - 1; i > 0; i--) {
|
|
50594
|
-
if (remaining[i] === " ") {
|
|
50595
|
-
breakPoint = i;
|
|
50596
|
-
break;
|
|
50597
|
-
}
|
|
50598
|
-
}
|
|
50599
|
-
lines.push(remaining.slice(0, breakPoint));
|
|
50600
|
-
remaining = remaining.slice(breakPoint).trimStart();
|
|
50601
|
-
}
|
|
50602
|
-
return lines;
|
|
50603
|
-
}
|
|
50604
|
-
function formatTable(data) {
|
|
50605
|
-
const items = extractItems(data);
|
|
50606
|
-
if (items.length === 0) {
|
|
50607
|
-
return "";
|
|
50608
|
-
}
|
|
50609
|
-
const headers = ["NAMESPACE", "NAME", "LABELS"];
|
|
50610
|
-
const widths = [9, 27, 30];
|
|
50611
|
-
const rows = [];
|
|
50612
|
-
for (const item of items) {
|
|
50613
|
-
const row = [
|
|
50614
|
-
getStringField(item, "namespace") || "<None>",
|
|
50615
|
-
getStringField(item, "name") || "<None>",
|
|
50616
|
-
formatLabels(item) || "<None>"
|
|
50617
|
-
];
|
|
50618
|
-
const wrappedCells = row.map((cell, i) => wrapText2(cell, widths[i]));
|
|
50619
|
-
const maxLines = Math.max(...wrappedCells.map((c) => c.length));
|
|
50620
|
-
const wrappedRows = [];
|
|
50621
|
-
for (let line = 0; line < maxLines; line++) {
|
|
50622
|
-
wrappedRows.push(wrappedCells.map((c) => c[line] ?? ""));
|
|
50623
|
-
}
|
|
50624
|
-
rows.push(wrappedRows);
|
|
50625
|
-
}
|
|
50626
|
-
const lines = [];
|
|
50627
|
-
const boxLine = "+" + widths.map((w) => "-".repeat(w + 2)).join("+") + "+";
|
|
50628
|
-
lines.push(boxLine);
|
|
50629
|
-
lines.push(
|
|
50630
|
-
"|" + headers.map((h, i) => {
|
|
50631
|
-
const padding = widths[i] - h.length;
|
|
50632
|
-
const leftPad = Math.floor(padding / 2);
|
|
50633
|
-
const rightPad = padding - leftPad;
|
|
50634
|
-
return " " + " ".repeat(leftPad) + h + " ".repeat(rightPad) + " ";
|
|
50635
|
-
}).join("|") + "|"
|
|
50636
|
-
);
|
|
50637
|
-
lines.push(boxLine);
|
|
50638
|
-
for (const wrappedRows of rows) {
|
|
50639
|
-
for (const row of wrappedRows) {
|
|
50640
|
-
lines.push(
|
|
50641
|
-
"|" + row.map((cell, i) => {
|
|
50642
|
-
const padding = widths[i] - cell.length;
|
|
50643
|
-
return " " + cell + " ".repeat(padding) + " ";
|
|
50644
|
-
}).join("|") + "|"
|
|
50645
|
-
);
|
|
50646
|
-
}
|
|
50647
|
-
lines.push(boxLine);
|
|
50648
|
-
}
|
|
50649
|
-
return lines.join("\n");
|
|
50650
|
-
}
|
|
50651
|
-
function formatTSV(data) {
|
|
50652
|
-
const items = extractItems(data);
|
|
50653
|
-
if (items.length === 0) {
|
|
50654
|
-
return "";
|
|
50655
|
-
}
|
|
50656
|
-
const allKeys = /* @__PURE__ */ new Set();
|
|
50657
|
-
for (const item of items) {
|
|
50658
|
-
Object.keys(item).forEach((k) => allKeys.add(k));
|
|
50659
|
-
}
|
|
50660
|
-
const priority = ["name", "namespace", "status", "created", "modified"];
|
|
50661
|
-
const headers = [
|
|
50662
|
-
...priority.filter((p) => allKeys.has(p)),
|
|
50663
|
-
...[...allKeys].filter((k) => !priority.includes(k)).sort()
|
|
50664
|
-
];
|
|
50665
|
-
const lines = [];
|
|
50666
|
-
for (const item of items) {
|
|
50667
|
-
const values = headers.map((h) => {
|
|
50668
|
-
const val = item[h];
|
|
50669
|
-
if (val === null || val === void 0) return "";
|
|
50670
|
-
if (typeof val === "object") return JSON.stringify(val);
|
|
50671
|
-
return String(val);
|
|
50672
|
-
});
|
|
50673
|
-
lines.push(values.join(" "));
|
|
50674
|
-
}
|
|
50675
|
-
return lines.join("\n");
|
|
50676
|
-
}
|
|
50677
|
-
function formatAPIError(statusCode, body, operation) {
|
|
50678
|
-
const lines = [];
|
|
50679
|
-
lines.push(`ERROR: ${operation} failed (HTTP ${statusCode})`);
|
|
50680
|
-
if (body && typeof body === "object") {
|
|
50681
|
-
const errResp = body;
|
|
50682
|
-
if (errResp.message) {
|
|
50683
|
-
lines.push(` Message: ${errResp.message}`);
|
|
50684
|
-
}
|
|
50685
|
-
if (errResp.code) {
|
|
50686
|
-
lines.push(` Code: ${errResp.code}`);
|
|
50687
|
-
}
|
|
50688
|
-
if (errResp.details) {
|
|
50689
|
-
lines.push(` Details: ${errResp.details}`);
|
|
50690
|
-
}
|
|
50691
|
-
}
|
|
50692
|
-
switch (statusCode) {
|
|
50693
|
-
case 401:
|
|
50694
|
-
lines.push(
|
|
50695
|
-
"\nHint: Authentication failed. Check your credentials with 'login profile show'"
|
|
50696
|
-
);
|
|
50697
|
-
break;
|
|
50698
|
-
case 403:
|
|
50699
|
-
lines.push(
|
|
50700
|
-
"\nHint: Permission denied. You may not have access to this resource."
|
|
50701
|
-
);
|
|
50702
|
-
break;
|
|
50703
|
-
case 404:
|
|
50704
|
-
lines.push(
|
|
50705
|
-
"\nHint: Resource not found. Verify the name and namespace are correct."
|
|
50706
|
-
);
|
|
50707
|
-
break;
|
|
50708
|
-
case 409:
|
|
50709
|
-
lines.push(
|
|
50710
|
-
"\nHint: Conflict - resource may already exist or be in a conflicting state."
|
|
50711
|
-
);
|
|
50712
|
-
break;
|
|
50713
|
-
case 429:
|
|
50714
|
-
lines.push("\nHint: Rate limited. Please wait and try again.");
|
|
50715
|
-
break;
|
|
50716
|
-
case 500:
|
|
50717
|
-
case 502:
|
|
50718
|
-
case 503:
|
|
50719
|
-
lines.push(
|
|
50720
|
-
"\nHint: Server error. Please try again later or contact support."
|
|
50721
|
-
);
|
|
50722
|
-
break;
|
|
50723
|
-
}
|
|
50724
|
-
return lines.join("\n");
|
|
50898
|
+
},
|
|
50899
|
+
[completer, isShowing, hide]
|
|
50900
|
+
);
|
|
50901
|
+
const navigateUp = (0, import_react27.useCallback)(() => {
|
|
50902
|
+
if (!isShowing || suggestions.length === 0) return;
|
|
50903
|
+
setSelectedIndex(
|
|
50904
|
+
(current) => current > 0 ? current - 1 : suggestions.length - 1
|
|
50905
|
+
);
|
|
50906
|
+
}, [isShowing, suggestions.length]);
|
|
50907
|
+
const navigateDown = (0, import_react27.useCallback)(() => {
|
|
50908
|
+
if (!isShowing || suggestions.length === 0) return;
|
|
50909
|
+
setSelectedIndex(
|
|
50910
|
+
(current) => current < suggestions.length - 1 ? current + 1 : 0
|
|
50911
|
+
);
|
|
50912
|
+
}, [isShowing, suggestions.length]);
|
|
50913
|
+
const selectCurrent = (0, import_react27.useCallback)(() => {
|
|
50914
|
+
if (!isShowing || suggestions.length === 0) return null;
|
|
50915
|
+
const selected = suggestions.at(selectedIndex);
|
|
50916
|
+
hide();
|
|
50917
|
+
return selected ?? null;
|
|
50918
|
+
}, [isShowing, suggestions, selectedIndex, hide]);
|
|
50919
|
+
return {
|
|
50920
|
+
suggestions,
|
|
50921
|
+
selectedIndex,
|
|
50922
|
+
isShowing,
|
|
50923
|
+
triggerCompletion,
|
|
50924
|
+
navigateUp,
|
|
50925
|
+
navigateDown,
|
|
50926
|
+
selectCurrent,
|
|
50927
|
+
hide,
|
|
50928
|
+
filterSuggestions
|
|
50929
|
+
};
|
|
50725
50930
|
}
|
|
50726
50931
|
|
|
50727
|
-
// src/
|
|
50728
|
-
|
|
50729
|
-
|
|
50730
|
-
|
|
50731
|
-
|
|
50732
|
-
|
|
50733
|
-
|
|
50734
|
-
|
|
50735
|
-
|
|
50736
|
-
"
|
|
50737
|
-
|
|
50738
|
-
|
|
50739
|
-
|
|
50740
|
-
|
|
50741
|
-
"
|
|
50742
|
-
|
|
50743
|
-
|
|
50744
|
-
|
|
50745
|
-
|
|
50746
|
-
` ${CLI_NAME} --interactive Force interactive REPL mode`,
|
|
50747
|
-
"",
|
|
50748
|
-
...formatDomainsSection(),
|
|
50749
|
-
"",
|
|
50750
|
-
...formatGlobalFlags(),
|
|
50751
|
-
"",
|
|
50752
|
-
...formatEnvVarsSection(),
|
|
50753
|
-
"",
|
|
50754
|
-
...formatConfigSection(),
|
|
50755
|
-
"",
|
|
50756
|
-
"NAVIGATION (Interactive Mode)",
|
|
50757
|
-
" <domain> Navigate into a domain (e.g., 'dns', 'lb')",
|
|
50758
|
-
" /domain Navigate directly to domain from anywhere",
|
|
50759
|
-
" .. Go up one level",
|
|
50760
|
-
" / Return to root",
|
|
50761
|
-
" context Show current navigation context",
|
|
50762
|
-
"",
|
|
50763
|
-
"BUILTINS",
|
|
50764
|
-
" help Show this help",
|
|
50765
|
-
" domains List all available domains",
|
|
50766
|
-
" clear Clear the screen",
|
|
50767
|
-
" history Show command history",
|
|
50768
|
-
" quit, exit Exit the shell",
|
|
50769
|
-
""
|
|
50770
|
-
];
|
|
50932
|
+
// src/output/formatter.ts
|
|
50933
|
+
var import_yaml3 = __toESM(require_dist(), 1);
|
|
50934
|
+
function formatOutput(data, format = "yaml") {
|
|
50935
|
+
if (format === "none") {
|
|
50936
|
+
return "";
|
|
50937
|
+
}
|
|
50938
|
+
switch (format) {
|
|
50939
|
+
case "json":
|
|
50940
|
+
return formatJSON(data);
|
|
50941
|
+
case "yaml":
|
|
50942
|
+
return formatYAML(data);
|
|
50943
|
+
case "table":
|
|
50944
|
+
case "text":
|
|
50945
|
+
return formatTable(data);
|
|
50946
|
+
case "tsv":
|
|
50947
|
+
return formatTSV(data);
|
|
50948
|
+
default:
|
|
50949
|
+
return formatYAML(data);
|
|
50950
|
+
}
|
|
50771
50951
|
}
|
|
50772
|
-
function
|
|
50773
|
-
return
|
|
50774
|
-
"GLOBAL FLAGS",
|
|
50775
|
-
" -v, --version Show version number",
|
|
50776
|
-
" -h, --help Show this help",
|
|
50777
|
-
" -i, --interactive Force interactive mode",
|
|
50778
|
-
" --no-color Disable color output",
|
|
50779
|
-
" -o, --output <fmt> Output format (json, yaml, table)",
|
|
50780
|
-
" -ns, --namespace <ns> Target namespace"
|
|
50781
|
-
];
|
|
50952
|
+
function formatJSON(data) {
|
|
50953
|
+
return JSON.stringify(data, null, 2);
|
|
50782
50954
|
}
|
|
50783
|
-
function
|
|
50784
|
-
return
|
|
50955
|
+
function formatYAML(data) {
|
|
50956
|
+
return import_yaml3.default.stringify(data, { indent: 2 });
|
|
50785
50957
|
}
|
|
50786
|
-
function
|
|
50787
|
-
|
|
50788
|
-
|
|
50789
|
-
|
|
50790
|
-
|
|
50791
|
-
|
|
50792
|
-
|
|
50793
|
-
if (domain.complexity) meta.push(`Complexity: ${domain.complexity}`);
|
|
50794
|
-
output.push(colorDim(` ${meta.join(" | ")}`));
|
|
50795
|
-
output.push("");
|
|
50796
|
-
}
|
|
50797
|
-
output.push("USAGE");
|
|
50798
|
-
output.push(` ${CLI_NAME} ${domain.name} <action> [options]`);
|
|
50799
|
-
output.push("");
|
|
50800
|
-
output.push("ACTIONS");
|
|
50801
|
-
const actionDescriptions2 = {
|
|
50802
|
-
list: "List resources",
|
|
50803
|
-
get: "Get a specific resource by name",
|
|
50804
|
-
create: "Create a new resource",
|
|
50805
|
-
delete: "Delete a resource",
|
|
50806
|
-
replace: "Replace a resource configuration",
|
|
50807
|
-
apply: "Apply configuration from file",
|
|
50808
|
-
status: "Get resource status",
|
|
50809
|
-
patch: "Patch a resource",
|
|
50810
|
-
"add-labels": "Add labels to a resource",
|
|
50811
|
-
"remove-labels": "Remove labels from a resource"
|
|
50812
|
-
};
|
|
50813
|
-
for (const action of validActions) {
|
|
50814
|
-
const desc = actionDescriptions2[action] ?? action;
|
|
50815
|
-
output.push(` ${action.padEnd(16)} ${desc}`);
|
|
50816
|
-
}
|
|
50817
|
-
output.push("");
|
|
50818
|
-
output.push("EXAMPLES");
|
|
50819
|
-
output.push(` ${CLI_NAME} ${domain.name} list`);
|
|
50820
|
-
output.push(` ${CLI_NAME} ${domain.name} get my-resource`);
|
|
50821
|
-
output.push(
|
|
50822
|
-
` ${CLI_NAME} ${domain.name} create my-resource -f config.yaml`
|
|
50823
|
-
);
|
|
50824
|
-
output.push(` ${CLI_NAME} ${domain.name} delete my-resource`);
|
|
50825
|
-
output.push("");
|
|
50826
|
-
if (domain.useCases && domain.useCases.length > 0) {
|
|
50827
|
-
output.push("USE CASES");
|
|
50828
|
-
for (const useCase of domain.useCases.slice(0, 5)) {
|
|
50829
|
-
output.push(` - ${useCase}`);
|
|
50958
|
+
function extractItems(data) {
|
|
50959
|
+
if (data && typeof data === "object" && "items" in data) {
|
|
50960
|
+
const items = data.items;
|
|
50961
|
+
if (Array.isArray(items)) {
|
|
50962
|
+
return items.filter(
|
|
50963
|
+
(item) => item !== null && typeof item === "object"
|
|
50964
|
+
);
|
|
50830
50965
|
}
|
|
50831
|
-
output.push("");
|
|
50832
50966
|
}
|
|
50833
|
-
if (
|
|
50834
|
-
|
|
50835
|
-
|
|
50836
|
-
|
|
50967
|
+
if (Array.isArray(data)) {
|
|
50968
|
+
return data.filter(
|
|
50969
|
+
(item) => item !== null && typeof item === "object"
|
|
50970
|
+
);
|
|
50837
50971
|
}
|
|
50838
|
-
if (
|
|
50839
|
-
|
|
50840
|
-
output.push(` ${domain.aliases.join(", ")}`);
|
|
50841
|
-
output.push("");
|
|
50972
|
+
if (data && typeof data === "object") {
|
|
50973
|
+
return [data];
|
|
50842
50974
|
}
|
|
50843
|
-
|
|
50844
|
-
output.push("");
|
|
50845
|
-
return output;
|
|
50975
|
+
return [];
|
|
50846
50976
|
}
|
|
50847
|
-
function
|
|
50848
|
-
const
|
|
50849
|
-
|
|
50850
|
-
|
|
50851
|
-
|
|
50852
|
-
|
|
50853
|
-
|
|
50854
|
-
|
|
50855
|
-
|
|
50856
|
-
desc: "Get a specific resource by name",
|
|
50857
|
-
usage: `${CLI_NAME} ${domainName} get <name> [-o json|yaml|table]`
|
|
50858
|
-
},
|
|
50859
|
-
create: {
|
|
50860
|
-
desc: "Create a new resource",
|
|
50861
|
-
usage: `${CLI_NAME} ${domainName} create <name> -f <file.yaml>`
|
|
50862
|
-
},
|
|
50863
|
-
delete: {
|
|
50864
|
-
desc: "Delete a resource by name",
|
|
50865
|
-
usage: `${CLI_NAME} ${domainName} delete <name>`
|
|
50866
|
-
},
|
|
50867
|
-
replace: {
|
|
50868
|
-
desc: "Replace an existing resource configuration",
|
|
50869
|
-
usage: `${CLI_NAME} ${domainName} replace <name> -f <file.yaml>`
|
|
50870
|
-
},
|
|
50871
|
-
apply: {
|
|
50872
|
-
desc: "Apply configuration from a file (create or update)",
|
|
50873
|
-
usage: `${CLI_NAME} ${domainName} apply -f <file.yaml>`
|
|
50874
|
-
},
|
|
50875
|
-
status: {
|
|
50876
|
-
desc: "Get the current status of a resource",
|
|
50877
|
-
usage: `${CLI_NAME} ${domainName} status <name>`
|
|
50878
|
-
},
|
|
50879
|
-
patch: {
|
|
50880
|
-
desc: "Patch specific fields of a resource",
|
|
50881
|
-
usage: `${CLI_NAME} ${domainName} patch <name> -f <patch.yaml>`
|
|
50882
|
-
},
|
|
50883
|
-
"add-labels": {
|
|
50884
|
-
desc: "Add labels to a resource",
|
|
50885
|
-
usage: `${CLI_NAME} ${domainName} add-labels <name> key=value`
|
|
50886
|
-
},
|
|
50887
|
-
"remove-labels": {
|
|
50888
|
-
desc: "Remove labels from a resource",
|
|
50889
|
-
usage: `${CLI_NAME} ${domainName} remove-labels <name> key`
|
|
50890
|
-
}
|
|
50891
|
-
};
|
|
50892
|
-
const actionInfo = actionDescriptions2[action] ?? {
|
|
50893
|
-
desc: `Execute ${action} operation`,
|
|
50894
|
-
usage: `${CLI_NAME} ${domainName} ${action} [options]`
|
|
50895
|
-
};
|
|
50896
|
-
return [
|
|
50897
|
-
"",
|
|
50898
|
-
colorBoldWhite(`${displayDomain} - ${action}`),
|
|
50899
|
-
"",
|
|
50900
|
-
` ${actionInfo.desc}`,
|
|
50901
|
-
"",
|
|
50902
|
-
"USAGE",
|
|
50903
|
-
` ${actionInfo.usage}`,
|
|
50904
|
-
"",
|
|
50905
|
-
"OPTIONS",
|
|
50906
|
-
" -n, --name <name> Resource name",
|
|
50907
|
-
" -ns, --namespace <ns> Target namespace",
|
|
50908
|
-
" -o, --output <fmt> Output format (json, yaml, table)",
|
|
50909
|
-
" -f, --file <path> Configuration file",
|
|
50910
|
-
"",
|
|
50911
|
-
colorDim(`For domain help, run: ${CLI_NAME} ${domainName} --help`),
|
|
50912
|
-
""
|
|
50913
|
-
];
|
|
50977
|
+
function getStringField(obj, key) {
|
|
50978
|
+
const value = obj[key];
|
|
50979
|
+
if (typeof value === "string") {
|
|
50980
|
+
return value;
|
|
50981
|
+
}
|
|
50982
|
+
if (value !== null && value !== void 0) {
|
|
50983
|
+
return String(value);
|
|
50984
|
+
}
|
|
50985
|
+
return "";
|
|
50914
50986
|
}
|
|
50915
|
-
function
|
|
50916
|
-
const
|
|
50917
|
-
|
|
50918
|
-
|
|
50919
|
-
return formatDomainHelp(domainInfo);
|
|
50987
|
+
function formatLabels(obj) {
|
|
50988
|
+
const labels = obj["labels"];
|
|
50989
|
+
if (!labels || typeof labels !== "object") {
|
|
50990
|
+
return "";
|
|
50920
50991
|
}
|
|
50921
|
-
|
|
50922
|
-
|
|
50923
|
-
|
|
50924
|
-
|
|
50925
|
-
return formatActionsHelp();
|
|
50926
|
-
case "navigation":
|
|
50927
|
-
case "nav":
|
|
50928
|
-
return formatNavigationHelp();
|
|
50929
|
-
case "env":
|
|
50930
|
-
case "environment":
|
|
50931
|
-
return ["", ...formatEnvironmentVariables(), ""];
|
|
50932
|
-
case "flags":
|
|
50933
|
-
return ["", ...formatGlobalFlags(), ""];
|
|
50934
|
-
default:
|
|
50935
|
-
return [
|
|
50936
|
-
"",
|
|
50937
|
-
`Unknown help topic: ${topic}`,
|
|
50938
|
-
"",
|
|
50939
|
-
"Available topics:",
|
|
50940
|
-
" domains List all available domains",
|
|
50941
|
-
" actions List available actions",
|
|
50942
|
-
" navigation Navigation commands",
|
|
50943
|
-
" env Environment variables",
|
|
50944
|
-
" flags Global flags",
|
|
50945
|
-
" <domain> Help for a specific domain (e.g., 'help dns')",
|
|
50946
|
-
""
|
|
50947
|
-
];
|
|
50992
|
+
const labelMap = labels;
|
|
50993
|
+
const entries = Object.entries(labelMap).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}:${v}`);
|
|
50994
|
+
if (entries.length === 0) {
|
|
50995
|
+
return "";
|
|
50948
50996
|
}
|
|
50997
|
+
return `map[${entries.join(" ")}]`;
|
|
50949
50998
|
}
|
|
50950
|
-
function
|
|
50951
|
-
|
|
50952
|
-
|
|
50953
|
-
for (const domain of domainRegistry.values()) {
|
|
50954
|
-
const category = domain.category ?? "Other";
|
|
50955
|
-
if (!categories.has(category)) {
|
|
50956
|
-
categories.set(category, []);
|
|
50957
|
-
}
|
|
50958
|
-
categories.get(category)?.push(domain);
|
|
50999
|
+
function wrapText3(text, maxWidth) {
|
|
51000
|
+
if (text.length <= maxWidth) {
|
|
51001
|
+
return [text];
|
|
50959
51002
|
}
|
|
50960
|
-
const
|
|
50961
|
-
|
|
50962
|
-
|
|
50963
|
-
|
|
50964
|
-
|
|
50965
|
-
|
|
50966
|
-
|
|
50967
|
-
|
|
50968
|
-
|
|
50969
|
-
|
|
50970
|
-
|
|
50971
|
-
|
|
50972
|
-
output.push(` ${"".padEnd(24)} Aliases:${aliases}`);
|
|
51003
|
+
const lines = [];
|
|
51004
|
+
let remaining = text;
|
|
51005
|
+
while (remaining.length > 0) {
|
|
51006
|
+
if (remaining.length <= maxWidth) {
|
|
51007
|
+
lines.push(remaining);
|
|
51008
|
+
break;
|
|
51009
|
+
}
|
|
51010
|
+
let breakPoint = maxWidth;
|
|
51011
|
+
for (let i = maxWidth - 1; i > 0; i--) {
|
|
51012
|
+
if (remaining[i] === " ") {
|
|
51013
|
+
breakPoint = i;
|
|
51014
|
+
break;
|
|
50973
51015
|
}
|
|
50974
51016
|
}
|
|
50975
|
-
|
|
51017
|
+
lines.push(remaining.slice(0, breakPoint));
|
|
51018
|
+
remaining = remaining.slice(breakPoint).trimStart();
|
|
50976
51019
|
}
|
|
50977
|
-
return
|
|
51020
|
+
return lines;
|
|
50978
51021
|
}
|
|
50979
|
-
function
|
|
50980
|
-
|
|
50981
|
-
|
|
50982
|
-
|
|
50983
|
-
|
|
50984
|
-
|
|
50985
|
-
|
|
50986
|
-
|
|
50987
|
-
|
|
50988
|
-
|
|
50989
|
-
|
|
50990
|
-
|
|
50991
|
-
|
|
50992
|
-
|
|
50993
|
-
|
|
50994
|
-
|
|
50995
|
-
|
|
50996
|
-
|
|
50997
|
-
|
|
50998
|
-
|
|
50999
|
-
|
|
51000
|
-
|
|
51001
|
-
|
|
51002
|
-
|
|
51003
|
-
|
|
51022
|
+
function formatTable(data) {
|
|
51023
|
+
const items = extractItems(data);
|
|
51024
|
+
if (items.length === 0) {
|
|
51025
|
+
return "";
|
|
51026
|
+
}
|
|
51027
|
+
const headers = ["NAMESPACE", "NAME", "LABELS"];
|
|
51028
|
+
const widths = [9, 27, 30];
|
|
51029
|
+
const rows = [];
|
|
51030
|
+
for (const item of items) {
|
|
51031
|
+
const row = [
|
|
51032
|
+
getStringField(item, "namespace") || "<None>",
|
|
51033
|
+
getStringField(item, "name") || "<None>",
|
|
51034
|
+
formatLabels(item) || "<None>"
|
|
51035
|
+
];
|
|
51036
|
+
const wrappedCells = row.map((cell, i) => wrapText3(cell, widths[i]));
|
|
51037
|
+
const maxLines = Math.max(...wrappedCells.map((c) => c.length));
|
|
51038
|
+
const wrappedRows = [];
|
|
51039
|
+
for (let line = 0; line < maxLines; line++) {
|
|
51040
|
+
wrappedRows.push(wrappedCells.map((c) => c[line] ?? ""));
|
|
51041
|
+
}
|
|
51042
|
+
rows.push(wrappedRows);
|
|
51043
|
+
}
|
|
51044
|
+
const lines = [];
|
|
51045
|
+
const boxLine = "+" + widths.map((w) => "-".repeat(w + 2)).join("+") + "+";
|
|
51046
|
+
lines.push(boxLine);
|
|
51047
|
+
lines.push(
|
|
51048
|
+
"|" + headers.map((h, i) => {
|
|
51049
|
+
const padding = widths[i] - h.length;
|
|
51050
|
+
const leftPad = Math.floor(padding / 2);
|
|
51051
|
+
const rightPad = padding - leftPad;
|
|
51052
|
+
return " " + " ".repeat(leftPad) + h + " ".repeat(rightPad) + " ";
|
|
51053
|
+
}).join("|") + "|"
|
|
51054
|
+
);
|
|
51055
|
+
lines.push(boxLine);
|
|
51056
|
+
for (const wrappedRows of rows) {
|
|
51057
|
+
for (const row of wrappedRows) {
|
|
51058
|
+
lines.push(
|
|
51059
|
+
"|" + row.map((cell, i) => {
|
|
51060
|
+
const padding = widths[i] - cell.length;
|
|
51061
|
+
return " " + cell + " ".repeat(padding) + " ";
|
|
51062
|
+
}).join("|") + "|"
|
|
51063
|
+
);
|
|
51064
|
+
}
|
|
51065
|
+
lines.push(boxLine);
|
|
51066
|
+
}
|
|
51067
|
+
return lines.join("\n");
|
|
51004
51068
|
}
|
|
51005
|
-
function
|
|
51006
|
-
|
|
51007
|
-
|
|
51008
|
-
|
|
51009
|
-
|
|
51010
|
-
|
|
51011
|
-
|
|
51012
|
-
|
|
51013
|
-
|
|
51014
|
-
|
|
51015
|
-
|
|
51016
|
-
|
|
51017
|
-
|
|
51018
|
-
" context Show current navigation context",
|
|
51019
|
-
" ctx Alias for context",
|
|
51020
|
-
"",
|
|
51021
|
-
"EXAMPLES",
|
|
51022
|
-
" xcsh> dns # Enter dns domain",
|
|
51023
|
-
" dns> list # Execute list in dns context",
|
|
51024
|
-
" dns> .. # Return to root",
|
|
51025
|
-
" xcsh> /waf # Jump directly to waf",
|
|
51026
|
-
" waf> /dns # Jump from waf to dns",
|
|
51027
|
-
""
|
|
51069
|
+
function formatTSV(data) {
|
|
51070
|
+
const items = extractItems(data);
|
|
51071
|
+
if (items.length === 0) {
|
|
51072
|
+
return "";
|
|
51073
|
+
}
|
|
51074
|
+
const allKeys = /* @__PURE__ */ new Set();
|
|
51075
|
+
for (const item of items) {
|
|
51076
|
+
Object.keys(item).forEach((k) => allKeys.add(k));
|
|
51077
|
+
}
|
|
51078
|
+
const priority = ["name", "namespace", "status", "created", "modified"];
|
|
51079
|
+
const headers = [
|
|
51080
|
+
...priority.filter((p) => allKeys.has(p)),
|
|
51081
|
+
...[...allKeys].filter((k) => !priority.includes(k)).sort()
|
|
51028
51082
|
];
|
|
51083
|
+
const lines = [];
|
|
51084
|
+
for (const item of items) {
|
|
51085
|
+
const values = headers.map((h) => {
|
|
51086
|
+
const val = item[h];
|
|
51087
|
+
if (val === null || val === void 0) return "";
|
|
51088
|
+
if (typeof val === "object") return JSON.stringify(val);
|
|
51089
|
+
return String(val);
|
|
51090
|
+
});
|
|
51091
|
+
lines.push(values.join(" "));
|
|
51092
|
+
}
|
|
51093
|
+
return lines.join("\n");
|
|
51029
51094
|
}
|
|
51030
|
-
function
|
|
51031
|
-
const
|
|
51032
|
-
|
|
51033
|
-
|
|
51034
|
-
|
|
51035
|
-
|
|
51036
|
-
|
|
51037
|
-
|
|
51038
|
-
|
|
51095
|
+
function formatAPIError(statusCode, body, operation) {
|
|
51096
|
+
const lines = [];
|
|
51097
|
+
lines.push(`ERROR: ${operation} failed (HTTP ${statusCode})`);
|
|
51098
|
+
if (body && typeof body === "object") {
|
|
51099
|
+
const errResp = body;
|
|
51100
|
+
if (errResp.message) {
|
|
51101
|
+
lines.push(` Message: ${errResp.message}`);
|
|
51102
|
+
}
|
|
51103
|
+
if (errResp.code) {
|
|
51104
|
+
lines.push(` Code: ${errResp.code}`);
|
|
51105
|
+
}
|
|
51106
|
+
if (errResp.details) {
|
|
51107
|
+
lines.push(` Details: ${errResp.details}`);
|
|
51108
|
+
}
|
|
51039
51109
|
}
|
|
51040
|
-
|
|
51110
|
+
switch (statusCode) {
|
|
51111
|
+
case 401:
|
|
51112
|
+
lines.push(
|
|
51113
|
+
"\nHint: Authentication failed. Check your credentials with 'login profile show'"
|
|
51114
|
+
);
|
|
51115
|
+
break;
|
|
51116
|
+
case 403:
|
|
51117
|
+
lines.push(
|
|
51118
|
+
"\nHint: Permission denied. You may not have access to this resource."
|
|
51119
|
+
);
|
|
51120
|
+
break;
|
|
51121
|
+
case 404:
|
|
51122
|
+
lines.push(
|
|
51123
|
+
"\nHint: Resource not found. Verify the name and namespace are correct."
|
|
51124
|
+
);
|
|
51125
|
+
break;
|
|
51126
|
+
case 409:
|
|
51127
|
+
lines.push(
|
|
51128
|
+
"\nHint: Conflict - resource may already exist or be in a conflicting state."
|
|
51129
|
+
);
|
|
51130
|
+
break;
|
|
51131
|
+
case 429:
|
|
51132
|
+
lines.push("\nHint: Rate limited. Please wait and try again.");
|
|
51133
|
+
break;
|
|
51134
|
+
case 500:
|
|
51135
|
+
case 502:
|
|
51136
|
+
case 503:
|
|
51137
|
+
lines.push(
|
|
51138
|
+
"\nHint: Server error. Please try again later or contact support."
|
|
51139
|
+
);
|
|
51140
|
+
break;
|
|
51141
|
+
}
|
|
51142
|
+
return lines.join("\n");
|
|
51041
51143
|
}
|
|
51042
51144
|
|
|
51043
51145
|
// src/repl/executor.ts
|