@robinmordasiewicz/f5xc-xcsh 6.35.0 → 6.37.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/dist/index.js CHANGED
@@ -44530,9 +44530,9 @@ var generatedDomains = /* @__PURE__ */ new Map([
44530
44530
  ["observability", {
44531
44531
  name: "observability",
44532
44532
  displayName: "Observability",
44533
- description: "Deploy synthetic monitors to validate DNS resolution and HTTP service health from multiple geographic locations. Define monitoring schedules, response time thresholds, and alerting conditions for proactive issue detection. Access health summaries, historical trends, and detailed reports for certificate status and service availability. Integrate monitoring data with dashboards to visualize health patterns and identify performance degradation before user impact.",
44533
+ description: "Set up synthetic monitoring for DNS resolution and HTTP services across AWS regions. Generate health reports with historical trends and summary dashboards. Monitor certificate validity, track response times, and aggregate results by namespace for capacity planning.",
44534
44534
  descriptionShort: "Configure synthetic monitors and health checks",
44535
- descriptionMedium: "Set up DNS and HTTP monitoring with alerting thresholds. Track certificate expiration and service availability across regions.",
44535
+ descriptionMedium: "Define DNS and HTTP monitors with regional testing. Track certificate expiration and service availability across zones.",
44536
44536
  aliases: ["obs", "monitoring", "synth"],
44537
44537
  complexity: "advanced",
44538
44538
  isPreview: false,
@@ -44600,9 +44600,9 @@ var generatedDomains = /* @__PURE__ */ new Map([
44600
44600
  ["sites", {
44601
44601
  name: "sites",
44602
44602
  displayName: "Sites",
44603
- description: "Create virtual and physical edge deployments spanning multiple providers. Establish AWS Transit Gateway connections and secure tunnel configurations for hybrid connectivity. Integrate external container orchestration systems as customer edge nodes with managed control planes. Define virtual groupings using label selectors to apply consistent policies across distributed infrastructure. Enable secure mesh communication between edge nodes and cloud workloads with automated certificate management.",
44604
- descriptionShort: "Deploy and manage edge infrastructure",
44605
- descriptionMedium: "Configure cloud provider resources on AWS, Azure, and GCP. Set up VPC peering, transit gateways, and VPN tunnels for hybrid environments.",
44603
+ description: "Deploy edge nodes across AWS, Azure, and GCP with automated provisioning. Configure VPC peering, transit gateway attachments, and VPN tunnel settings. Define virtual groupings with label selectors for policy targeting. Manage Kubernetes cluster integrations and secure mesh deployments. Monitor node health, validate configurations, and set IP prefix allocations.",
44604
+ descriptionShort: "Deploy edge nodes across cloud providers",
44605
+ descriptionMedium: "Configure AWS, Azure, GCP deployments with VPC integration. Manage transit gateways and VPN tunnels.",
44606
44606
  aliases: ["site", "deployment"],
44607
44607
  complexity: "advanced",
44608
44608
  isPreview: false,
@@ -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.35.0") {
45358
- return "6.35.0";
45357
+ if ("6.37.0") {
45358
+ return "6.37.0";
45359
45359
  }
45360
45360
  if (process.env.XCSH_VERSION) {
45361
45361
  return process.env.XCSH_VERSION;
@@ -46843,6 +46843,450 @@ function useHistory(options) {
46843
46843
  // src/repl/hooks/useCompletion.ts
46844
46844
  var import_react27 = __toESM(require_react(), 1);
46845
46845
 
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"
46879
+ }
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}`);
46888
+ }
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
+ }
46915
+ }
46916
+ if (currentLine.trim()) {
46917
+ lines.push(currentLine);
46918
+ }
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
+ "",
46940
+ ...formatDomainsSection(),
46941
+ "",
46942
+ ...formatGlobalFlags(),
46943
+ "",
46944
+ ...formatEnvVarsSection(),
46945
+ "",
46946
+ ...formatConfigSection(),
46947
+ "",
46948
+ "NAVIGATION (Interactive Mode)",
46949
+ " <domain> Navigate into a domain (e.g., 'dns', 'lb')",
46950
+ " /domain Navigate directly to domain from anywhere",
46951
+ " .. Go up one level",
46952
+ " / Return to root",
46953
+ " context Show current navigation context",
46954
+ "",
46955
+ "BUILTINS",
46956
+ " help Show this help",
46957
+ " domains List all available domains",
46958
+ " clear Clear the screen",
46959
+ " history Show command history",
46960
+ " quit, exit Exit the shell",
46961
+ ""
46962
+ ];
46963
+ }
46964
+ function formatGlobalFlags() {
46965
+ return [
46966
+ "GLOBAL FLAGS",
46967
+ " -v, --version Show version number",
46968
+ " -h, --help Show this help",
46969
+ " --no-color Disable color output",
46970
+ " -o, --output <fmt> Output format (json, yaml, table)",
46971
+ " -ns, --namespace <ns> Target namespace"
46972
+ ];
46973
+ }
46974
+ function formatEnvironmentVariables() {
46975
+ return formatEnvVarsSection();
46976
+ }
46977
+ function formatDomainHelp(domain) {
46978
+ const output = ["", colorBoldWhite(`${domain.displayName}`), ""];
46979
+ output.push(` ${domain.description}`);
46980
+ output.push("");
46981
+ if (domain.category || domain.complexity) {
46982
+ const meta = [];
46983
+ if (domain.category) meta.push(`Category: ${domain.category}`);
46984
+ if (domain.complexity) meta.push(`Complexity: ${domain.complexity}`);
46985
+ output.push(colorDim(` ${meta.join(" | ")}`));
46986
+ output.push("");
46987
+ }
46988
+ output.push("USAGE");
46989
+ output.push(` ${CLI_NAME} ${domain.name} <action> [options]`);
46990
+ output.push("");
46991
+ output.push("ACTIONS");
46992
+ const actionDescriptions2 = {
46993
+ list: "List resources",
46994
+ get: "Get a specific resource by name",
46995
+ create: "Create a new resource",
46996
+ delete: "Delete a resource",
46997
+ replace: "Replace a resource configuration",
46998
+ apply: "Apply configuration from file",
46999
+ status: "Get resource status",
47000
+ patch: "Patch a resource",
47001
+ "add-labels": "Add labels to a resource",
47002
+ "remove-labels": "Remove labels from a resource"
47003
+ };
47004
+ for (const action of validActions) {
47005
+ const desc = actionDescriptions2[action] ?? action;
47006
+ output.push(` ${action.padEnd(16)} ${desc}`);
47007
+ }
47008
+ output.push("");
47009
+ output.push("EXAMPLES");
47010
+ output.push(` ${CLI_NAME} ${domain.name} list`);
47011
+ output.push(` ${CLI_NAME} ${domain.name} get my-resource`);
47012
+ output.push(
47013
+ ` ${CLI_NAME} ${domain.name} create my-resource -f config.yaml`
47014
+ );
47015
+ output.push(` ${CLI_NAME} ${domain.name} delete my-resource`);
47016
+ output.push("");
47017
+ if (domain.useCases && domain.useCases.length > 0) {
47018
+ output.push("USE CASES");
47019
+ for (const useCase of domain.useCases.slice(0, 5)) {
47020
+ output.push(` - ${useCase}`);
47021
+ }
47022
+ output.push("");
47023
+ }
47024
+ if (domain.relatedDomains && domain.relatedDomains.length > 0) {
47025
+ output.push("RELATED DOMAINS");
47026
+ output.push(` ${domain.relatedDomains.join(", ")}`);
47027
+ output.push("");
47028
+ }
47029
+ if (domain.aliases && domain.aliases.length > 0) {
47030
+ output.push("ALIASES");
47031
+ output.push(` ${domain.aliases.join(", ")}`);
47032
+ output.push("");
47033
+ }
47034
+ output.push(colorDim(`For global options, run: ${CLI_NAME} --help`));
47035
+ output.push("");
47036
+ return output;
47037
+ }
47038
+ function formatActionHelp(domainName, action) {
47039
+ const domain = getDomainInfo(domainName);
47040
+ const displayDomain = domain?.displayName ?? domainName;
47041
+ const actionDescriptions2 = {
47042
+ list: {
47043
+ desc: "List all resources in the namespace",
47044
+ usage: `${CLI_NAME} ${domainName} list [--limit N] [--label key=value]`
47045
+ },
47046
+ get: {
47047
+ desc: "Get a specific resource by name",
47048
+ usage: `${CLI_NAME} ${domainName} get <name> [-o json|yaml|table]`
47049
+ },
47050
+ create: {
47051
+ desc: "Create a new resource",
47052
+ usage: `${CLI_NAME} ${domainName} create <name> -f <file.yaml>`
47053
+ },
47054
+ delete: {
47055
+ desc: "Delete a resource by name",
47056
+ usage: `${CLI_NAME} ${domainName} delete <name>`
47057
+ },
47058
+ replace: {
47059
+ desc: "Replace an existing resource configuration",
47060
+ usage: `${CLI_NAME} ${domainName} replace <name> -f <file.yaml>`
47061
+ },
47062
+ apply: {
47063
+ desc: "Apply configuration from a file (create or update)",
47064
+ usage: `${CLI_NAME} ${domainName} apply -f <file.yaml>`
47065
+ },
47066
+ status: {
47067
+ desc: "Get the current status of a resource",
47068
+ usage: `${CLI_NAME} ${domainName} status <name>`
47069
+ },
47070
+ patch: {
47071
+ desc: "Patch specific fields of a resource",
47072
+ usage: `${CLI_NAME} ${domainName} patch <name> -f <patch.yaml>`
47073
+ },
47074
+ "add-labels": {
47075
+ desc: "Add labels to a resource",
47076
+ usage: `${CLI_NAME} ${domainName} add-labels <name> key=value`
47077
+ },
47078
+ "remove-labels": {
47079
+ desc: "Remove labels from a resource",
47080
+ usage: `${CLI_NAME} ${domainName} remove-labels <name> key`
47081
+ }
47082
+ };
47083
+ const actionInfo = actionDescriptions2[action] ?? {
47084
+ desc: `Execute ${action} operation`,
47085
+ usage: `${CLI_NAME} ${domainName} ${action} [options]`
47086
+ };
47087
+ return [
47088
+ "",
47089
+ colorBoldWhite(`${displayDomain} - ${action}`),
47090
+ "",
47091
+ ` ${actionInfo.desc}`,
47092
+ "",
47093
+ "USAGE",
47094
+ ` ${actionInfo.usage}`,
47095
+ "",
47096
+ "OPTIONS",
47097
+ " -n, --name <name> Resource name",
47098
+ " -ns, --namespace <ns> Target namespace",
47099
+ " -o, --output <fmt> Output format (json, yaml, table)",
47100
+ " -f, --file <path> Configuration file",
47101
+ "",
47102
+ colorDim(`For domain help, run: ${CLI_NAME} ${domainName} --help`),
47103
+ ""
47104
+ ];
47105
+ }
47106
+ function formatTopicHelp(topic) {
47107
+ const lowerTopic = topic.toLowerCase();
47108
+ const domainInfo = getDomainInfo(lowerTopic);
47109
+ if (domainInfo) {
47110
+ return formatDomainHelp(domainInfo);
47111
+ }
47112
+ switch (lowerTopic) {
47113
+ case "domains":
47114
+ return formatDomainsHelp();
47115
+ case "actions":
47116
+ return formatActionsHelp();
47117
+ case "navigation":
47118
+ case "nav":
47119
+ return formatNavigationHelp();
47120
+ case "env":
47121
+ case "environment":
47122
+ return ["", ...formatEnvironmentVariables(), ""];
47123
+ case "flags":
47124
+ return ["", ...formatGlobalFlags(), ""];
47125
+ default:
47126
+ return [
47127
+ "",
47128
+ `Unknown help topic: ${topic}`,
47129
+ "",
47130
+ "Available topics:",
47131
+ " domains List all available domains",
47132
+ " actions List available actions",
47133
+ " navigation Navigation commands",
47134
+ " env Environment variables",
47135
+ " flags Global flags",
47136
+ " <domain> Help for a specific domain (e.g., 'help dns')",
47137
+ ""
47138
+ ];
47139
+ }
47140
+ }
47141
+ function formatDomainsHelp() {
47142
+ const output = ["", colorBoldWhite("Available Domains"), ""];
47143
+ const categories = /* @__PURE__ */ new Map();
47144
+ for (const domain of domainRegistry.values()) {
47145
+ const category = domain.category ?? "Other";
47146
+ if (!categories.has(category)) {
47147
+ categories.set(category, []);
47148
+ }
47149
+ categories.get(category)?.push(domain);
47150
+ }
47151
+ const sortedCategories = Array.from(categories.keys()).sort();
47152
+ for (const category of sortedCategories) {
47153
+ const domains = categories.get(category) ?? [];
47154
+ output.push(colorBoldWhite(` ${category}`));
47155
+ for (const domain of domains.sort(
47156
+ (a, b) => a.name.localeCompare(b.name)
47157
+ )) {
47158
+ const aliases = domain.aliases.length > 0 ? colorDim(` (${domain.aliases.join(", ")})`) : "";
47159
+ output.push(
47160
+ ` ${domain.name.padEnd(24)} ${domain.descriptionShort}`
47161
+ );
47162
+ if (aliases) {
47163
+ output.push(` ${"".padEnd(24)} Aliases:${aliases}`);
47164
+ }
47165
+ }
47166
+ output.push("");
47167
+ }
47168
+ return output;
47169
+ }
47170
+ function formatActionsHelp() {
47171
+ return [
47172
+ "",
47173
+ colorBoldWhite("Available Actions"),
47174
+ "",
47175
+ " list List all resources in the namespace",
47176
+ " get Get a specific resource by name",
47177
+ " create Create a new resource from a file",
47178
+ " delete Delete a resource by name",
47179
+ " replace Replace a resource configuration",
47180
+ " apply Apply configuration (create or update)",
47181
+ " status Get resource status",
47182
+ " patch Patch specific fields of a resource",
47183
+ " add-labels Add labels to a resource",
47184
+ " remove-labels Remove labels from a resource",
47185
+ "",
47186
+ "USAGE",
47187
+ ` ${CLI_NAME} <domain> <action> [options]`,
47188
+ "",
47189
+ "EXAMPLES",
47190
+ ` ${CLI_NAME} dns list`,
47191
+ ` ${CLI_NAME} lb get my-loadbalancer`,
47192
+ ` ${CLI_NAME} waf create my-policy -f policy.yaml`,
47193
+ ""
47194
+ ];
47195
+ }
47196
+ function formatNavigationHelp() {
47197
+ return [
47198
+ "",
47199
+ colorBoldWhite("Navigation Commands"),
47200
+ "",
47201
+ " <domain> Navigate into a domain context",
47202
+ " /<domain> Navigate directly to domain from anywhere",
47203
+ " .. Go up one level in context",
47204
+ " / Return to root context",
47205
+ " back Go up one level (same as ..)",
47206
+ " root Return to root (same as /)",
47207
+ "",
47208
+ "CONTEXT DISPLAY",
47209
+ " context Show current navigation context",
47210
+ " ctx Alias for context",
47211
+ "",
47212
+ "EXAMPLES",
47213
+ " xcsh> dns # Enter dns domain",
47214
+ " dns> list # Execute list in dns context",
47215
+ " dns> .. # Return to root",
47216
+ " xcsh> /waf # Jump directly to waf",
47217
+ " waf> /dns # Jump from waf to dns",
47218
+ ""
47219
+ ];
47220
+ }
47221
+ function formatDomainsSection() {
47222
+ const output = ["DOMAINS"];
47223
+ const domains = Array.from(domainRegistry.values()).sort(
47224
+ (a, b) => a.name.localeCompare(b.name)
47225
+ );
47226
+ const maxNameLen = Math.max(...domains.map((d) => d.name.length));
47227
+ for (const domain of domains) {
47228
+ const padding = " ".repeat(maxNameLen - domain.name.length + 2);
47229
+ output.push(` ${domain.name}${padding}${domain.descriptionShort}`);
47230
+ }
47231
+ return output;
47232
+ }
47233
+ function formatCustomDomainHelp(domain) {
47234
+ const output = ["", colorBoldWhite(domain.name), ""];
47235
+ output.push("DESCRIPTION");
47236
+ output.push(...wrapText2(domain.description, 80, 2));
47237
+ output.push("");
47238
+ output.push("USAGE");
47239
+ output.push(` ${CLI_NAME} ${domain.name} <command> [options]`);
47240
+ output.push("");
47241
+ if (domain.subcommands.size > 0) {
47242
+ output.push("SUBCOMMANDS");
47243
+ for (const [name, group] of domain.subcommands) {
47244
+ output.push(` ${name.padEnd(16)} ${group.descriptionShort}`);
47245
+ }
47246
+ output.push("");
47247
+ }
47248
+ if (domain.commands.size > 0) {
47249
+ output.push("COMMANDS");
47250
+ for (const [name, cmd] of domain.commands) {
47251
+ output.push(` ${name.padEnd(16)} ${cmd.descriptionShort}`);
47252
+ }
47253
+ output.push("");
47254
+ }
47255
+ output.push(colorDim(`For global options, run: ${CLI_NAME} --help`));
47256
+ output.push("");
47257
+ return output;
47258
+ }
47259
+ function formatSubcommandHelp(domainName, subcommand) {
47260
+ const output = [
47261
+ "",
47262
+ colorBoldWhite(`${domainName} ${subcommand.name}`),
47263
+ ""
47264
+ ];
47265
+ output.push("DESCRIPTION");
47266
+ output.push(...wrapText2(subcommand.description, 80, 2));
47267
+ output.push("");
47268
+ output.push("USAGE");
47269
+ output.push(
47270
+ ` ${CLI_NAME} ${domainName} ${subcommand.name} <command> [options]`
47271
+ );
47272
+ output.push("");
47273
+ if (subcommand.commands.size > 0) {
47274
+ output.push("COMMANDS");
47275
+ for (const [name, cmd] of subcommand.commands) {
47276
+ const usage = cmd.usage ? ` ${cmd.usage}` : "";
47277
+ output.push(
47278
+ ` ${name}${usage.padEnd(16 - name.length)} ${cmd.descriptionShort}`
47279
+ );
47280
+ }
47281
+ output.push("");
47282
+ }
47283
+ output.push(
47284
+ colorDim(`For domain help, run: ${CLI_NAME} ${domainName} --help`)
47285
+ );
47286
+ output.push("");
47287
+ return output;
47288
+ }
47289
+
46846
47290
  // src/domains/registry.ts
46847
47291
  var DomainRegistry = class {
46848
47292
  domains = /* @__PURE__ */ new Map();
@@ -47024,45 +47468,24 @@ var DomainRegistry = class {
47024
47468
  return suggestions;
47025
47469
  }
47026
47470
  /**
47027
- * Show help for a domain
47471
+ * Show help for a domain using the unified help formatter.
47472
+ * This ensures consistent professional formatting across all domains.
47028
47473
  */
47029
47474
  showDomainHelp(domain) {
47030
- const output = [`${domain.name} - ${domain.description}`, ``];
47031
- if (domain.subcommands.size > 0) {
47032
- output.push(`Subcommands:`);
47033
- for (const [name, group] of domain.subcommands) {
47034
- output.push(` ${name} ${group.description}`);
47035
- }
47036
- output.push(``);
47037
- }
47038
- if (domain.commands.size > 0) {
47039
- output.push(`Commands:`);
47040
- for (const [name, cmd] of domain.commands) {
47041
- output.push(` ${name} ${cmd.description}`);
47042
- }
47043
- }
47044
47475
  return {
47045
- output,
47476
+ output: formatCustomDomainHelp(domain),
47046
47477
  shouldExit: false,
47047
47478
  shouldClear: false,
47048
47479
  contextChanged: false
47049
47480
  };
47050
47481
  }
47051
47482
  /**
47052
- * Show help for a subcommand group
47483
+ * Show help for a subcommand group using the unified help formatter.
47484
+ * This ensures consistent professional formatting across all subcommands.
47053
47485
  */
47054
47486
  showSubcommandHelp(domain, subgroup) {
47055
- const output = [
47056
- `${domain.name} ${subgroup.name} - ${subgroup.description}`,
47057
- ``,
47058
- `Commands:`
47059
- ];
47060
- for (const [name, cmd] of subgroup.commands) {
47061
- const usage = cmd.usage ? ` ${cmd.usage}` : "";
47062
- output.push(` ${name}${usage} ${cmd.description}`);
47063
- }
47064
47487
  return {
47065
- output,
47488
+ output: formatSubcommandHelp(domain.name, subgroup),
47066
47489
  shouldExit: false,
47067
47490
  shouldClear: false,
47068
47491
  contextChanged: false
@@ -47545,74 +47968,18 @@ var listCommand2 = {
47545
47968
  return errorResult(`Failed to list namespaces: ${message}`);
47546
47969
  }
47547
47970
  }
47548
- };
47549
- var contextSubcommands = {
47550
- name: "context",
47551
- 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.",
47552
- descriptionShort: "Manage default namespace context",
47553
- descriptionMedium: "Set, display, and list namespaces for scoping operations without explicit namespace flags.",
47554
- commands: /* @__PURE__ */ new Map([
47555
- ["show", showCommand2],
47556
- ["set", setCommand],
47557
- ["list", listCommand2]
47558
- ])
47559
- };
47560
-
47561
- // src/config/envvars.ts
47562
- var EnvVarRegistry = [
47563
- {
47564
- name: `${ENV_PREFIX}_API_URL`,
47565
- description: "API endpoint URL",
47566
- relatedFlag: "",
47567
- required: true
47568
- },
47569
- {
47570
- name: `${ENV_PREFIX}_API_TOKEN`,
47571
- description: "API authentication token",
47572
- relatedFlag: "",
47573
- required: true
47574
- },
47575
- {
47576
- name: `${ENV_PREFIX}_NAMESPACE`,
47577
- description: "Default namespace",
47578
- relatedFlag: "-ns"
47579
- },
47580
- {
47581
- name: `${ENV_PREFIX}_OUTPUT_FORMAT`,
47582
- description: "Output format (json, yaml, table)",
47583
- relatedFlag: "-o"
47584
- },
47585
- {
47586
- name: `${ENV_PREFIX}_LOGO`,
47587
- description: "Logo display mode (auto, image, ascii, both, none)",
47588
- relatedFlag: "--logo"
47589
- },
47590
- {
47591
- name: "NO_COLOR",
47592
- description: "Disable color output",
47593
- relatedFlag: "--no-color"
47594
- }
47595
- ];
47596
- function formatEnvVarsSection() {
47597
- const maxLen = Math.max(...EnvVarRegistry.map((e) => e.name.length));
47598
- const lines = ["ENVIRONMENT VARIABLES"];
47599
- for (const env3 of EnvVarRegistry) {
47600
- const padding = " ".repeat(maxLen - env3.name.length + 3);
47601
- const flagNote = env3.relatedFlag ? ` [${env3.relatedFlag}]` : "";
47602
- lines.push(` ${env3.name}${padding}${env3.description}${flagNote}`);
47603
- }
47604
- return lines;
47605
- }
47606
- function formatConfigSection() {
47607
- return [
47608
- "CONFIGURATION",
47609
- ` Config file: ~/${CONFIG_FILE_NAME}`,
47610
- " Priority: CLI flags > environment variables > config file > defaults",
47611
- "",
47612
- "DOCUMENTATION",
47613
- ` ${DOCS_URL}`
47614
- ];
47615
- }
47971
+ };
47972
+ var contextSubcommands = {
47973
+ name: "context",
47974
+ 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.",
47975
+ descriptionShort: "Manage default namespace context",
47976
+ descriptionMedium: "Set, display, and list namespaces for scoping operations without explicit namespace flags.",
47977
+ commands: /* @__PURE__ */ new Map([
47978
+ ["show", showCommand2],
47979
+ ["set", setCommand],
47980
+ ["list", listCommand2]
47981
+ ])
47982
+ };
47616
47983
 
47617
47984
  // src/config/settings.ts
47618
47985
  var import_yaml2 = __toESM(require_dist(), 1);
@@ -49165,7 +49532,7 @@ _xcsh_completions() {
49165
49532
  local commands="${domainNames} ${allAliases.join(" ")} help quit exit clear history"
49166
49533
  local actions="${actions}"
49167
49534
  local builtins="help quit exit clear history context ctx"
49168
- local global_flags="--help -h --version -v --interactive -i --no-color --output -o --namespace -ns"
49535
+ local global_flags="--help -h --version -v --no-color --output -o --namespace -ns"
49169
49536
 
49170
49537
  # Handle completion based on position
49171
49538
  case \${cword} in
@@ -49247,7 +49614,6 @@ _xcsh() {
49247
49614
  global_opts=(
49248
49615
  '(-h --help)'{-h,--help}'[Show help information]'
49249
49616
  '(-v --version)'{-v,--version}'[Show version number]'
49250
- '(-i --interactive)'{-i,--interactive}'[Force interactive mode]'
49251
49617
  '--no-color[Disable color output]'
49252
49618
  '(-o --output)'{-o,--output}'[Output format]:format:(json yaml table)'
49253
49619
  '(-ns --namespace)'{-ns,--namespace}'[Namespace]:namespace:_xcsh_namespaces'
@@ -49361,7 +49727,6 @@ complete -c xcsh -f
49361
49727
  # Global options
49362
49728
  complete -c xcsh -s h -l help -d 'Show help information'
49363
49729
  complete -c xcsh -s v -l version -d 'Show version number'
49364
- complete -c xcsh -s i -l interactive -d 'Force interactive mode'
49365
49730
  complete -c xcsh -l no-color -d 'Disable color output'
49366
49731
  complete -c xcsh -s o -l output -d 'Output format' -xa 'json yaml table'
49367
49732
  complete -c xcsh -l namespace -s ns -d 'Namespace' -xa 'default system shared'
@@ -50537,574 +50902,240 @@ function useCompletion(options) {
50537
50902
  }, [isShowing, suggestions.length]);
50538
50903
  const navigateDown = (0, import_react27.useCallback)(() => {
50539
50904
  if (!isShowing || suggestions.length === 0) return;
50540
- setSelectedIndex(
50541
- (current) => current < suggestions.length - 1 ? current + 1 : 0
50542
- );
50543
- }, [isShowing, suggestions.length]);
50544
- const selectCurrent = (0, import_react27.useCallback)(() => {
50545
- if (!isShowing || suggestions.length === 0) return null;
50546
- const selected = suggestions.at(selectedIndex);
50547
- hide();
50548
- return selected ?? null;
50549
- }, [isShowing, suggestions, selectedIndex, hide]);
50550
- return {
50551
- suggestions,
50552
- selectedIndex,
50553
- isShowing,
50554
- triggerCompletion,
50555
- navigateUp,
50556
- navigateDown,
50557
- selectCurrent,
50558
- hide,
50559
- filterSuggestions
50560
- };
50561
- }
50562
-
50563
- // src/output/formatter.ts
50564
- var import_yaml3 = __toESM(require_dist(), 1);
50565
- function formatOutput(data, format = "yaml") {
50566
- if (format === "none") {
50567
- return "";
50568
- }
50569
- switch (format) {
50570
- case "json":
50571
- return formatJSON(data);
50572
- case "yaml":
50573
- return formatYAML(data);
50574
- case "table":
50575
- case "text":
50576
- return formatTable(data);
50577
- case "tsv":
50578
- return formatTSV(data);
50579
- default:
50580
- return formatYAML(data);
50581
- }
50582
- }
50583
- function formatJSON(data) {
50584
- return JSON.stringify(data, null, 2);
50585
- }
50586
- function formatYAML(data) {
50587
- return import_yaml3.default.stringify(data, { indent: 2 });
50588
- }
50589
- function extractItems(data) {
50590
- if (data && typeof data === "object" && "items" in data) {
50591
- const items = data.items;
50592
- if (Array.isArray(items)) {
50593
- return items.filter(
50594
- (item) => item !== null && typeof item === "object"
50595
- );
50596
- }
50597
- }
50598
- if (Array.isArray(data)) {
50599
- return data.filter(
50600
- (item) => item !== null && typeof item === "object"
50601
- );
50602
- }
50603
- if (data && typeof data === "object") {
50604
- return [data];
50605
- }
50606
- return [];
50607
- }
50608
- function getStringField(obj, key) {
50609
- const value = obj[key];
50610
- if (typeof value === "string") {
50611
- return value;
50612
- }
50613
- if (value !== null && value !== void 0) {
50614
- return String(value);
50615
- }
50616
- return "";
50617
- }
50618
- function formatLabels(obj) {
50619
- const labels = obj["labels"];
50620
- if (!labels || typeof labels !== "object") {
50621
- return "";
50622
- }
50623
- const labelMap = labels;
50624
- const entries = Object.entries(labelMap).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}:${v}`);
50625
- if (entries.length === 0) {
50626
- return "";
50627
- }
50628
- return `map[${entries.join(" ")}]`;
50629
- }
50630
- function wrapText2(text, maxWidth) {
50631
- if (text.length <= maxWidth) {
50632
- return [text];
50633
- }
50634
- const lines = [];
50635
- let remaining = text;
50636
- while (remaining.length > 0) {
50637
- if (remaining.length <= maxWidth) {
50638
- lines.push(remaining);
50639
- break;
50640
- }
50641
- let breakPoint = maxWidth;
50642
- for (let i = maxWidth - 1; i > 0; i--) {
50643
- if (remaining[i] === " ") {
50644
- breakPoint = i;
50645
- break;
50646
- }
50647
- }
50648
- lines.push(remaining.slice(0, breakPoint));
50649
- remaining = remaining.slice(breakPoint).trimStart();
50650
- }
50651
- return lines;
50652
- }
50653
- function formatTable(data) {
50654
- const items = extractItems(data);
50655
- if (items.length === 0) {
50656
- return "";
50657
- }
50658
- const headers = ["NAMESPACE", "NAME", "LABELS"];
50659
- const widths = [9, 27, 30];
50660
- const rows = [];
50661
- for (const item of items) {
50662
- const row = [
50663
- getStringField(item, "namespace") || "<None>",
50664
- getStringField(item, "name") || "<None>",
50665
- formatLabels(item) || "<None>"
50666
- ];
50667
- const wrappedCells = row.map((cell, i) => wrapText2(cell, widths[i]));
50668
- const maxLines = Math.max(...wrappedCells.map((c) => c.length));
50669
- const wrappedRows = [];
50670
- for (let line = 0; line < maxLines; line++) {
50671
- wrappedRows.push(wrappedCells.map((c) => c[line] ?? ""));
50672
- }
50673
- rows.push(wrappedRows);
50674
- }
50675
- const lines = [];
50676
- const boxLine = "+" + widths.map((w) => "-".repeat(w + 2)).join("+") + "+";
50677
- lines.push(boxLine);
50678
- lines.push(
50679
- "|" + headers.map((h, i) => {
50680
- const padding = widths[i] - h.length;
50681
- const leftPad = Math.floor(padding / 2);
50682
- const rightPad = padding - leftPad;
50683
- return " " + " ".repeat(leftPad) + h + " ".repeat(rightPad) + " ";
50684
- }).join("|") + "|"
50685
- );
50686
- lines.push(boxLine);
50687
- for (const wrappedRows of rows) {
50688
- for (const row of wrappedRows) {
50689
- lines.push(
50690
- "|" + row.map((cell, i) => {
50691
- const padding = widths[i] - cell.length;
50692
- return " " + cell + " ".repeat(padding) + " ";
50693
- }).join("|") + "|"
50694
- );
50695
- }
50696
- lines.push(boxLine);
50697
- }
50698
- return lines.join("\n");
50699
- }
50700
- function formatTSV(data) {
50701
- const items = extractItems(data);
50702
- if (items.length === 0) {
50703
- return "";
50704
- }
50705
- const allKeys = /* @__PURE__ */ new Set();
50706
- for (const item of items) {
50707
- Object.keys(item).forEach((k) => allKeys.add(k));
50708
- }
50709
- const priority = ["name", "namespace", "status", "created", "modified"];
50710
- const headers = [
50711
- ...priority.filter((p) => allKeys.has(p)),
50712
- ...[...allKeys].filter((k) => !priority.includes(k)).sort()
50713
- ];
50714
- const lines = [];
50715
- for (const item of items) {
50716
- const values = headers.map((h) => {
50717
- const val = item[h];
50718
- if (val === null || val === void 0) return "";
50719
- if (typeof val === "object") return JSON.stringify(val);
50720
- return String(val);
50721
- });
50722
- lines.push(values.join(" "));
50723
- }
50724
- return lines.join("\n");
50725
- }
50726
- function formatAPIError(statusCode, body, operation) {
50727
- const lines = [];
50728
- lines.push(`ERROR: ${operation} failed (HTTP ${statusCode})`);
50729
- if (body && typeof body === "object") {
50730
- const errResp = body;
50731
- if (errResp.message) {
50732
- lines.push(` Message: ${errResp.message}`);
50733
- }
50734
- if (errResp.code) {
50735
- lines.push(` Code: ${errResp.code}`);
50736
- }
50737
- if (errResp.details) {
50738
- lines.push(` Details: ${errResp.details}`);
50739
- }
50740
- }
50741
- switch (statusCode) {
50742
- case 401:
50743
- lines.push(
50744
- "\nHint: Authentication failed. Check your credentials with 'login profile show'"
50745
- );
50746
- break;
50747
- case 403:
50748
- lines.push(
50749
- "\nHint: Permission denied. You may not have access to this resource."
50750
- );
50751
- break;
50752
- case 404:
50753
- lines.push(
50754
- "\nHint: Resource not found. Verify the name and namespace are correct."
50755
- );
50756
- break;
50757
- case 409:
50758
- lines.push(
50759
- "\nHint: Conflict - resource may already exist or be in a conflicting state."
50760
- );
50761
- break;
50762
- case 429:
50763
- lines.push("\nHint: Rate limited. Please wait and try again.");
50764
- break;
50765
- case 500:
50766
- case 502:
50767
- case 503:
50768
- lines.push(
50769
- "\nHint: Server error. Please try again later or contact support."
50770
- );
50771
- break;
50772
- }
50773
- return lines.join("\n");
50905
+ setSelectedIndex(
50906
+ (current) => current < suggestions.length - 1 ? current + 1 : 0
50907
+ );
50908
+ }, [isShowing, suggestions.length]);
50909
+ const selectCurrent = (0, import_react27.useCallback)(() => {
50910
+ if (!isShowing || suggestions.length === 0) return null;
50911
+ const selected = suggestions.at(selectedIndex);
50912
+ hide();
50913
+ return selected ?? null;
50914
+ }, [isShowing, suggestions, selectedIndex, hide]);
50915
+ return {
50916
+ suggestions,
50917
+ selectedIndex,
50918
+ isShowing,
50919
+ triggerCompletion,
50920
+ navigateUp,
50921
+ navigateDown,
50922
+ selectCurrent,
50923
+ hide,
50924
+ filterSuggestions
50925
+ };
50774
50926
  }
50775
50927
 
50776
- // src/repl/help.ts
50777
- function wrapText3(text, width, indent) {
50778
- const prefix = " ".repeat(indent);
50779
- const words = text.split(/\s+/);
50780
- const lines = [];
50781
- let currentLine = prefix;
50782
- for (const word of words) {
50783
- if (currentLine.length + word.length + 1 > width && currentLine !== prefix) {
50784
- lines.push(currentLine);
50785
- currentLine = prefix + word;
50786
- } else {
50787
- currentLine += (currentLine === prefix ? "" : " ") + word;
50788
- }
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 "";
50789
50933
  }
50790
- if (currentLine.trim()) {
50791
- lines.push(currentLine);
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);
50792
50946
  }
50793
- return lines;
50794
- }
50795
- function formatRootHelp() {
50796
- return [
50797
- "",
50798
- colorBoldWhite(`${CLI_NAME} - ${CLI_FULL_NAME} v${CLI_VERSION}`),
50799
- "",
50800
- "DESCRIPTION",
50801
- ...wrapText3(CLI_DESCRIPTION_LONG, 80, 2),
50802
- "",
50803
- "USAGE",
50804
- ` ${CLI_NAME} Enter interactive REPL mode`,
50805
- ` ${CLI_NAME} <domain> <action> Execute command non-interactively`,
50806
- ` ${CLI_NAME} help [topic] Show help for a topic`,
50807
- "",
50808
- "EXAMPLES",
50809
- ` ${CLI_NAME} tenant_and_identity list namespace List all namespaces`,
50810
- ` ${CLI_NAME} virtual get http_loadbalancer Get a specific load balancer`,
50811
- ` ${CLI_NAME} dns list List DNS zones`,
50812
- ` ${CLI_NAME} waf list -ns prod List WAF policies in prod`,
50813
- ` ${CLI_NAME} --interactive Force interactive REPL mode`,
50814
- "",
50815
- ...formatDomainsSection(),
50816
- "",
50817
- ...formatGlobalFlags(),
50818
- "",
50819
- ...formatEnvVarsSection(),
50820
- "",
50821
- ...formatConfigSection(),
50822
- "",
50823
- "NAVIGATION (Interactive Mode)",
50824
- " <domain> Navigate into a domain (e.g., 'dns', 'lb')",
50825
- " /domain Navigate directly to domain from anywhere",
50826
- " .. Go up one level",
50827
- " / Return to root",
50828
- " context Show current navigation context",
50829
- "",
50830
- "BUILTINS",
50831
- " help Show this help",
50832
- " domains List all available domains",
50833
- " clear Clear the screen",
50834
- " history Show command history",
50835
- " quit, exit Exit the shell",
50836
- ""
50837
- ];
50838
50947
  }
50839
- function formatGlobalFlags() {
50840
- return [
50841
- "GLOBAL FLAGS",
50842
- " -v, --version Show version number",
50843
- " -h, --help Show this help",
50844
- " -i, --interactive Force interactive mode",
50845
- " --no-color Disable color output",
50846
- " -o, --output <fmt> Output format (json, yaml, table)",
50847
- " -ns, --namespace <ns> Target namespace"
50848
- ];
50948
+ function formatJSON(data) {
50949
+ return JSON.stringify(data, null, 2);
50849
50950
  }
50850
- function formatEnvironmentVariables() {
50851
- return formatEnvVarsSection();
50951
+ function formatYAML(data) {
50952
+ return import_yaml3.default.stringify(data, { indent: 2 });
50852
50953
  }
50853
- function formatDomainHelp(domain) {
50854
- const output = ["", colorBoldWhite(`${domain.displayName}`), ""];
50855
- output.push(` ${domain.description}`);
50856
- output.push("");
50857
- if (domain.category || domain.complexity) {
50858
- const meta = [];
50859
- if (domain.category) meta.push(`Category: ${domain.category}`);
50860
- if (domain.complexity) meta.push(`Complexity: ${domain.complexity}`);
50861
- output.push(colorDim(` ${meta.join(" | ")}`));
50862
- output.push("");
50863
- }
50864
- output.push("USAGE");
50865
- output.push(` ${CLI_NAME} ${domain.name} <action> [options]`);
50866
- output.push("");
50867
- output.push("ACTIONS");
50868
- const actionDescriptions2 = {
50869
- list: "List resources",
50870
- get: "Get a specific resource by name",
50871
- create: "Create a new resource",
50872
- delete: "Delete a resource",
50873
- replace: "Replace a resource configuration",
50874
- apply: "Apply configuration from file",
50875
- status: "Get resource status",
50876
- patch: "Patch a resource",
50877
- "add-labels": "Add labels to a resource",
50878
- "remove-labels": "Remove labels from a resource"
50879
- };
50880
- for (const action of validActions) {
50881
- const desc = actionDescriptions2[action] ?? action;
50882
- output.push(` ${action.padEnd(16)} ${desc}`);
50883
- }
50884
- output.push("");
50885
- output.push("EXAMPLES");
50886
- output.push(` ${CLI_NAME} ${domain.name} list`);
50887
- output.push(` ${CLI_NAME} ${domain.name} get my-resource`);
50888
- output.push(
50889
- ` ${CLI_NAME} ${domain.name} create my-resource -f config.yaml`
50890
- );
50891
- output.push(` ${CLI_NAME} ${domain.name} delete my-resource`);
50892
- output.push("");
50893
- if (domain.useCases && domain.useCases.length > 0) {
50894
- output.push("USE CASES");
50895
- for (const useCase of domain.useCases.slice(0, 5)) {
50896
- output.push(` - ${useCase}`);
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
+ );
50897
50961
  }
50898
- output.push("");
50899
50962
  }
50900
- if (domain.relatedDomains && domain.relatedDomains.length > 0) {
50901
- output.push("RELATED DOMAINS");
50902
- output.push(` ${domain.relatedDomains.join(", ")}`);
50903
- output.push("");
50963
+ if (Array.isArray(data)) {
50964
+ return data.filter(
50965
+ (item) => item !== null && typeof item === "object"
50966
+ );
50904
50967
  }
50905
- if (domain.aliases && domain.aliases.length > 0) {
50906
- output.push("ALIASES");
50907
- output.push(` ${domain.aliases.join(", ")}`);
50908
- output.push("");
50968
+ if (data && typeof data === "object") {
50969
+ return [data];
50909
50970
  }
50910
- output.push(colorDim(`For global options, run: ${CLI_NAME} --help`));
50911
- output.push("");
50912
- return output;
50971
+ return [];
50913
50972
  }
50914
- function formatActionHelp(domainName, action) {
50915
- const domain = getDomainInfo(domainName);
50916
- const displayDomain = domain?.displayName ?? domainName;
50917
- const actionDescriptions2 = {
50918
- list: {
50919
- desc: "List all resources in the namespace",
50920
- usage: `${CLI_NAME} ${domainName} list [--limit N] [--label key=value]`
50921
- },
50922
- get: {
50923
- desc: "Get a specific resource by name",
50924
- usage: `${CLI_NAME} ${domainName} get <name> [-o json|yaml|table]`
50925
- },
50926
- create: {
50927
- desc: "Create a new resource",
50928
- usage: `${CLI_NAME} ${domainName} create <name> -f <file.yaml>`
50929
- },
50930
- delete: {
50931
- desc: "Delete a resource by name",
50932
- usage: `${CLI_NAME} ${domainName} delete <name>`
50933
- },
50934
- replace: {
50935
- desc: "Replace an existing resource configuration",
50936
- usage: `${CLI_NAME} ${domainName} replace <name> -f <file.yaml>`
50937
- },
50938
- apply: {
50939
- desc: "Apply configuration from a file (create or update)",
50940
- usage: `${CLI_NAME} ${domainName} apply -f <file.yaml>`
50941
- },
50942
- status: {
50943
- desc: "Get the current status of a resource",
50944
- usage: `${CLI_NAME} ${domainName} status <name>`
50945
- },
50946
- patch: {
50947
- desc: "Patch specific fields of a resource",
50948
- usage: `${CLI_NAME} ${domainName} patch <name> -f <patch.yaml>`
50949
- },
50950
- "add-labels": {
50951
- desc: "Add labels to a resource",
50952
- usage: `${CLI_NAME} ${domainName} add-labels <name> key=value`
50953
- },
50954
- "remove-labels": {
50955
- desc: "Remove labels from a resource",
50956
- usage: `${CLI_NAME} ${domainName} remove-labels <name> key`
50957
- }
50958
- };
50959
- const actionInfo = actionDescriptions2[action] ?? {
50960
- desc: `Execute ${action} operation`,
50961
- usage: `${CLI_NAME} ${domainName} ${action} [options]`
50962
- };
50963
- return [
50964
- "",
50965
- colorBoldWhite(`${displayDomain} - ${action}`),
50966
- "",
50967
- ` ${actionInfo.desc}`,
50968
- "",
50969
- "USAGE",
50970
- ` ${actionInfo.usage}`,
50971
- "",
50972
- "OPTIONS",
50973
- " -n, --name <name> Resource name",
50974
- " -ns, --namespace <ns> Target namespace",
50975
- " -o, --output <fmt> Output format (json, yaml, table)",
50976
- " -f, --file <path> Configuration file",
50977
- "",
50978
- colorDim(`For domain help, run: ${CLI_NAME} ${domainName} --help`),
50979
- ""
50980
- ];
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 "";
50981
50982
  }
50982
- function formatTopicHelp(topic) {
50983
- const lowerTopic = topic.toLowerCase();
50984
- const domainInfo = getDomainInfo(lowerTopic);
50985
- if (domainInfo) {
50986
- return formatDomainHelp(domainInfo);
50983
+ function formatLabels(obj) {
50984
+ const labels = obj["labels"];
50985
+ if (!labels || typeof labels !== "object") {
50986
+ return "";
50987
50987
  }
50988
- switch (lowerTopic) {
50989
- case "domains":
50990
- return formatDomainsHelp();
50991
- case "actions":
50992
- return formatActionsHelp();
50993
- case "navigation":
50994
- case "nav":
50995
- return formatNavigationHelp();
50996
- case "env":
50997
- case "environment":
50998
- return ["", ...formatEnvironmentVariables(), ""];
50999
- case "flags":
51000
- return ["", ...formatGlobalFlags(), ""];
51001
- default:
51002
- return [
51003
- "",
51004
- `Unknown help topic: ${topic}`,
51005
- "",
51006
- "Available topics:",
51007
- " domains List all available domains",
51008
- " actions List available actions",
51009
- " navigation Navigation commands",
51010
- " env Environment variables",
51011
- " flags Global flags",
51012
- " <domain> Help for a specific domain (e.g., 'help dns')",
51013
- ""
51014
- ];
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 "";
51015
50992
  }
50993
+ return `map[${entries.join(" ")}]`;
51016
50994
  }
51017
- function formatDomainsHelp() {
51018
- const output = ["", colorBoldWhite("Available Domains"), ""];
51019
- const categories = /* @__PURE__ */ new Map();
51020
- for (const domain of domainRegistry.values()) {
51021
- const category = domain.category ?? "Other";
51022
- if (!categories.has(category)) {
51023
- categories.set(category, []);
51024
- }
51025
- categories.get(category)?.push(domain);
50995
+ function wrapText3(text, maxWidth) {
50996
+ if (text.length <= maxWidth) {
50997
+ return [text];
51026
50998
  }
51027
- const sortedCategories = Array.from(categories.keys()).sort();
51028
- for (const category of sortedCategories) {
51029
- const domains = categories.get(category) ?? [];
51030
- output.push(colorBoldWhite(` ${category}`));
51031
- for (const domain of domains.sort(
51032
- (a, b) => a.name.localeCompare(b.name)
51033
- )) {
51034
- const aliases = domain.aliases.length > 0 ? colorDim(` (${domain.aliases.join(", ")})`) : "";
51035
- output.push(
51036
- ` ${domain.name.padEnd(24)} ${domain.descriptionShort}`
51037
- );
51038
- if (aliases) {
51039
- output.push(` ${"".padEnd(24)} Aliases:${aliases}`);
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;
51040
51011
  }
51041
51012
  }
51042
- output.push("");
51013
+ lines.push(remaining.slice(0, breakPoint));
51014
+ remaining = remaining.slice(breakPoint).trimStart();
51043
51015
  }
51044
- return output;
51016
+ return lines;
51045
51017
  }
51046
- function formatActionsHelp() {
51047
- return [
51048
- "",
51049
- colorBoldWhite("Available Actions"),
51050
- "",
51051
- " list List all resources in the namespace",
51052
- " get Get a specific resource by name",
51053
- " create Create a new resource from a file",
51054
- " delete Delete a resource by name",
51055
- " replace Replace a resource configuration",
51056
- " apply Apply configuration (create or update)",
51057
- " status Get resource status",
51058
- " patch Patch specific fields of a resource",
51059
- " add-labels Add labels to a resource",
51060
- " remove-labels Remove labels from a resource",
51061
- "",
51062
- "USAGE",
51063
- ` ${CLI_NAME} <domain> <action> [options]`,
51064
- "",
51065
- "EXAMPLES",
51066
- ` ${CLI_NAME} dns list`,
51067
- ` ${CLI_NAME} lb get my-loadbalancer`,
51068
- ` ${CLI_NAME} waf create my-policy -f policy.yaml`,
51069
- ""
51070
- ];
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");
51071
51064
  }
51072
- function formatNavigationHelp() {
51073
- return [
51074
- "",
51075
- colorBoldWhite("Navigation Commands"),
51076
- "",
51077
- " <domain> Navigate into a domain context",
51078
- " /<domain> Navigate directly to domain from anywhere",
51079
- " .. Go up one level in context",
51080
- " / Return to root context",
51081
- " back Go up one level (same as ..)",
51082
- " root Return to root (same as /)",
51083
- "",
51084
- "CONTEXT DISPLAY",
51085
- " context Show current navigation context",
51086
- " ctx Alias for context",
51087
- "",
51088
- "EXAMPLES",
51089
- " xcsh> dns # Enter dns domain",
51090
- " dns> list # Execute list in dns context",
51091
- " dns> .. # Return to root",
51092
- " xcsh> /waf # Jump directly to waf",
51093
- " waf> /dns # Jump from waf to dns",
51094
- ""
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()
51095
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");
51096
51090
  }
51097
- function formatDomainsSection() {
51098
- const output = ["DOMAINS"];
51099
- const domains = Array.from(domainRegistry.values()).sort(
51100
- (a, b) => a.name.localeCompare(b.name)
51101
- );
51102
- const maxNameLen = Math.max(...domains.map((d) => d.name.length));
51103
- for (const domain of domains) {
51104
- const padding = " ".repeat(maxNameLen - domain.name.length + 2);
51105
- output.push(` ${domain.name}${padding}${domain.descriptionShort}`);
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
+ }
51106
51105
  }
51107
- return output;
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");
51108
51139
  }
51109
51140
 
51110
51141
  // src/repl/executor.ts
@@ -52210,7 +52241,7 @@ var program2 = new Command();
52210
52241
  program2.configureHelp({
52211
52242
  formatHelp: () => formatRootHelp().join("\n")
52212
52243
  });
52213
- program2.name(CLI_NAME).description("F5 Distributed Cloud Shell - Interactive CLI for F5 XC").version(CLI_VERSION, "-v, --version", "Show version number").option("-i, --interactive", "Force interactive mode").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(
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(
52214
52245
  async (commandArgs, options) => {
52215
52246
  if (options.help && commandArgs.length === 0) {
52216
52247
  formatRootHelp().forEach((line) => console.log(line));
@@ -52222,8 +52253,8 @@ program2.name(CLI_NAME).description("F5 Distributed Cloud Shell - Interactive CL
52222
52253
  if (options.logo && commandArgs.length > 0) {
52223
52254
  commandArgs.push("--logo", options.logo);
52224
52255
  }
52225
- if (commandArgs.length === 0 || options.interactive) {
52226
- if (!process.stdin.isTTY && !options.interactive) {
52256
+ if (commandArgs.length === 0) {
52257
+ if (!process.stdin.isTTY) {
52227
52258
  console.error(
52228
52259
  "Error: Interactive mode requires a terminal (TTY)."
52229
52260
  );