cloudburn 0.18.10 → 0.18.11

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +24 -13
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -118,7 +118,7 @@ The discovery config equivalent is `discovery.fail-on`.
118
118
  Discovery has a five-minute deadline. Use `--timeout <seconds>` to change it, for example `cloudburn discover --timeout 600`. If the deadline expires, the command exits with code 2 and reports the timeout.
119
119
 
120
120
  Discovery reuses fresh, complete evidence from a per-user cache at `$XDG_CACHE_HOME/cloudburn/evidence`, or
121
- `~/.cache/cloudburn/evidence` when `XDG_CACHE_HOME` is unset. Rules and configuration are evaluated on every run.
121
+ `~/.cache/cloudburn/evidence` when `XDG_CACHE_HOME` is unset, empty, or relative. Rules and configuration are evaluated on every run.
122
122
 
123
123
  ```bash
124
124
  cloudburn discover --cache refresh
package/dist/cli.js CHANGED
@@ -588,7 +588,7 @@ var renderTable = (response) => {
588
588
  ${regionsTable}`;
589
589
  }
590
590
  case "record-list":
591
- return response.rows.length === 0 ? response.emptyMessage : renderAsciiTable(response.rows, response.columns ?? inferColumns(response.rows));
591
+ return response.rows.length === 0 ? toTerminalSafeText(response.emptyMessage) : renderAsciiTable(response.rows, response.columns ?? inferColumns(response.rows));
592
592
  case "rule-list":
593
593
  return renderRuleTable(response.rules, response.emptyMessage);
594
594
  case "scan-result": {
@@ -607,7 +607,7 @@ ${regionsTable}`;
607
607
  const oldestObservation = evidence.map((entry) => entry.observedAt).sort()[0];
608
608
  sections.push(
609
609
  `Evidence: ${cachedCount} cached, ${evidence.length - cachedCount} collected; ${incompleteCount} incomplete.
610
- Oldest observation: ${oldestObservation}`
610
+ Oldest observation: ${toTerminalSafeText(oldestObservation ?? "")}`
611
611
  );
612
612
  }
613
613
  return sections.join("\n\n");
@@ -638,7 +638,7 @@ ${renderAsciiTable(diagnosticRows, diagnosticColumns)}`
638
638
  ]
639
639
  );
640
640
  case "string-list":
641
- return response.values.length === 0 ? response.emptyMessage : renderAsciiTable(
641
+ return response.values.length === 0 ? toTerminalSafeText(response.emptyMessage) : renderAsciiTable(
642
642
  response.values.map((value) => ({ [response.columnHeader]: value })),
643
643
  [{ key: response.columnHeader, header: response.columnHeader }]
644
644
  );
@@ -677,7 +677,7 @@ var inferColumns = (rows) => {
677
677
  };
678
678
  var renderRuleTable = (rules, emptyMessage) => {
679
679
  if (rules.length === 0) {
680
- return emptyMessage;
680
+ return toTerminalSafeText(emptyMessage);
681
681
  }
682
682
  return renderAsciiTable(
683
683
  rules.map((rule) => ({
@@ -704,12 +704,21 @@ var toTextCell = (value) => {
704
704
  }
705
705
  return JSON.stringify(value);
706
706
  };
707
- var toTableCell = (value) => {
708
- if (Array.isArray(value)) {
709
- return value.map((item) => toTextCell(item)).join(", ").replace(/\r?\n/g, "\\n");
707
+ var TERMINAL_UNSAFE_CHARACTERS = /\r?\n|[\u0000-\u001f\u007f-\u009f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/gu;
708
+ var NAMED_CONTROL_ESCAPES = { "\n": "\\n", "\r": "\\r", " ": "\\t" };
709
+ var escapeTerminalCharacter = (character) => {
710
+ if (character === "\r\n") {
711
+ return "\\n";
710
712
  }
711
- return toTextCell(value).replace(/\r?\n/g, "\\n");
713
+ const named = NAMED_CONTROL_ESCAPES[character];
714
+ if (named) {
715
+ return named;
716
+ }
717
+ const codePoint = character.codePointAt(0) ?? 0;
718
+ return codePoint <= 255 ? `\\x${codePoint.toString(16).padStart(2, "0")}` : `\\u${codePoint.toString(16).padStart(4, "0")}`;
712
719
  };
720
+ var toTerminalSafeText = (value) => value.replace(TERMINAL_UNSAFE_CHARACTERS, escapeTerminalCharacter);
721
+ var toTableCell = (value) => toTerminalSafeText(Array.isArray(value) ? value.map((item) => toTextCell(item)).join(", ") : toTextCell(value));
713
722
  var resolveTableColumns = (rows, columns) => {
714
723
  const visibleColumns = columns.filter((column) => rows.some((row) => toTableCell(row[column.key]).length > 0));
715
724
  return visibleColumns.length === 0 ? columns : visibleColumns;
@@ -802,7 +811,10 @@ var renderTableLines = (cells, widths) => {
802
811
  });
803
812
  };
804
813
  var renderAsciiTable = (rows, columns) => {
805
- const visibleColumns = resolveTableColumns(rows, columns);
814
+ const visibleColumns = resolveTableColumns(rows, columns).map((column) => ({
815
+ ...column,
816
+ header: toTerminalSafeText(column.header)
817
+ }));
806
818
  const widths = fitColumnWidths(visibleColumns, rows);
807
819
  const border = `+${widths.map((width) => "-".repeat(width + 2)).join("+")}+`;
808
820
  const header = renderTableLines(
@@ -1014,11 +1026,10 @@ var registerConfigCommand = (program) => {
1014
1026
  };
1015
1027
 
1016
1028
  // src/commands/discover.ts
1017
- import { homedir } from "os";
1018
- import { join as join2 } from "path";
1019
1029
  import {
1020
1030
  assertSupportedAwsRegion,
1021
1031
  CloudBurnClient,
1032
+ resolveCloudBurnCacheDirectory,
1022
1033
  resolveScanPolicy
1023
1034
  } from "@cloudburn/sdk";
1024
1035
  import { InvalidArgumentError as InvalidArgumentError3 } from "commander";
@@ -1233,7 +1244,7 @@ var registerDiscoverCommand = (program) => {
1233
1244
  const discoveryOptions = {
1234
1245
  cache: {
1235
1246
  mode: options.cache ?? "normal",
1236
- directory: options.cacheDir ?? join2(process.env.XDG_CACHE_HOME ?? join2(homedir(), ".cache"), "cloudburn", "evidence"),
1247
+ directory: options.cacheDir ?? resolveCloudBurnCacheDirectory("evidence"),
1237
1248
  ...options.cacheContext === void 0 ? {} : { authorizationContext: options.cacheContext }
1238
1249
  },
1239
1250
  target: resolveDiscoveryTarget(options.region)
@@ -1495,7 +1506,7 @@ var isCliEntrypoint = (moduleUrl, argvEntry = process.argv[1]) => {
1495
1506
  };
1496
1507
  var createProgram = () => {
1497
1508
  const program = createCliCommand();
1498
- program.name("cloudburn").usage("[command]").description("Know what you spend. Fix what you waste.").version("0.18.10").option("--debug", "Write execution trace messages to stderr").option("--format <format>", OUTPUT_FORMAT_OPTION_DESCRIPTION, parseOutputFormat);
1509
+ program.name("cloudburn").usage("[command]").description("Know what you spend. Fix what you waste.").version("0.18.11").option("--debug", "Write execution trace messages to stderr").option("--format <format>", OUTPUT_FORMAT_OPTION_DESCRIPTION, parseOutputFormat);
1499
1510
  configureCliHelp(program);
1500
1511
  program.exitOverride();
1501
1512
  registerCompletionCommand(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudburn",
3
- "version": "0.18.10",
3
+ "version": "0.18.11",
4
4
  "description": "Cloudburn CLI for cloud cost optimization",
5
5
  "homepage": "https://cloudburn.io/docs",
6
6
  "bugs": {
@@ -20,7 +20,7 @@
20
20
  ],
21
21
  "dependencies": {
22
22
  "commander": "^15.0.0",
23
- "@cloudburn/sdk": "0.38.1"
23
+ "@cloudburn/sdk": "0.38.2"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@biomejs/biome": "^2.5.12",