cloudburn 0.18.7 → 0.18.9
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/cli.js +50 -159
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -7,10 +7,10 @@ import { fileURLToPath } from "url";
|
|
|
7
7
|
import { CommanderError } from "commander";
|
|
8
8
|
|
|
9
9
|
// src/completion/engine.ts
|
|
10
|
-
var
|
|
10
|
+
var createCompletionTree = (command) => {
|
|
11
11
|
const help = command.createHelp();
|
|
12
12
|
return {
|
|
13
|
-
commands: help.visibleCommands(command).map((childCommand) =>
|
|
13
|
+
commands: help.visibleCommands(command).map((childCommand) => createCompletionTree(childCommand)),
|
|
14
14
|
name: command.name(),
|
|
15
15
|
options: collectVisibleOptions([...help.visibleOptions(command), ...help.visibleGlobalOptions(command)])
|
|
16
16
|
};
|
|
@@ -44,7 +44,6 @@ var parseOptionToken = (token) => {
|
|
|
44
44
|
name: token.slice(0, separatorIndex)
|
|
45
45
|
};
|
|
46
46
|
};
|
|
47
|
-
var createCompletionTree = (command) => buildCompletionTree(command);
|
|
48
47
|
var resolveCompletionSuggestions = (root, words) => {
|
|
49
48
|
const committedWords = words.length === 0 ? [] : words.slice(0, -1);
|
|
50
49
|
const partialWord = words.at(-1) ?? "";
|
|
@@ -478,69 +477,12 @@ var EXIT_CODE_POLICY_VIOLATION = 1;
|
|
|
478
477
|
var EXIT_CODE_RUNTIME_ERROR = 2;
|
|
479
478
|
|
|
480
479
|
// src/formatters/error.ts
|
|
481
|
-
import {
|
|
482
|
-
var
|
|
483
|
-
/([?&](?:access_token|authorization|token|x-amz-security-token|x-amz-signature|signature)=)[^&\s]+/gi,
|
|
484
|
-
"$1[redacted]"
|
|
485
|
-
).replace(/(Bearer\s+)[A-Za-z0-9._~+/-]+/gi, "$1[redacted]");
|
|
486
|
-
var formatError = (err) => {
|
|
487
|
-
const envelope = { error: categorize(err) };
|
|
488
|
-
return JSON.stringify(envelope, null, 2);
|
|
489
|
-
};
|
|
490
|
-
var categorize = (err) => {
|
|
491
|
-
if (!(err instanceof Error)) {
|
|
492
|
-
return { code: "RUNTIME_ERROR", message: "An unexpected error occurred." };
|
|
493
|
-
}
|
|
494
|
-
const code = "code" in err && typeof err.code === "string" ? err.code : void 0;
|
|
495
|
-
if (err.name === "CredentialsProviderError" || err.name === "ExpiredTokenException" || code === "CredentialsProviderError" || code === "ExpiredTokenException") {
|
|
496
|
-
return {
|
|
497
|
-
code: "CREDENTIALS_ERROR",
|
|
498
|
-
message: "AWS credentials not found or expired. Run 'aws sts get-caller-identity' to verify your session."
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
if (err.name.includes("AccessDenied") || code?.includes("AccessDenied") === true) {
|
|
502
|
-
return {
|
|
503
|
-
code: "ACCESS_DENIED",
|
|
504
|
-
message: sanitizeRuntimeErrorMessage(err.message).trim() || "Insufficient AWS permissions. Check your IAM role or policy."
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
if (err.code === "ENOENT") {
|
|
508
|
-
const path = err.path ?? "unknown";
|
|
509
|
-
return { code: "PATH_NOT_FOUND", message: `Path not found: ${path}` };
|
|
510
|
-
}
|
|
511
|
-
if (code && isAwsDiscoveryErrorCode(code)) {
|
|
512
|
-
return {
|
|
513
|
-
code,
|
|
514
|
-
message: sanitizeRuntimeErrorMessage(err.message).trim() || "AWS Resource Explorer discovery failed."
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
const sanitizedMessage = sanitizeRuntimeErrorMessage(err.message).trim();
|
|
518
|
-
return {
|
|
519
|
-
code: "RUNTIME_ERROR",
|
|
520
|
-
message: sanitizedMessage || "An unexpected error occurred."
|
|
521
|
-
};
|
|
522
|
-
};
|
|
480
|
+
import { categorizeError } from "@cloudburn/sdk";
|
|
481
|
+
var formatError = (err) => JSON.stringify({ error: categorizeError(err) }, null, 2);
|
|
523
482
|
|
|
524
483
|
// src/formatters/output.ts
|
|
484
|
+
import { flattenFindings } from "@cloudburn/sdk";
|
|
525
485
|
import { InvalidArgumentError } from "commander";
|
|
526
|
-
|
|
527
|
-
// src/formatters/shared.ts
|
|
528
|
-
var flattenScanResult = (result) => result.providers.flatMap(
|
|
529
|
-
(providerGroup) => providerGroup.rules.flatMap(
|
|
530
|
-
(ruleGroup) => ruleGroup.findings.map((finding) => ({
|
|
531
|
-
provider: providerGroup.provider,
|
|
532
|
-
ruleId: ruleGroup.ruleId,
|
|
533
|
-
service: ruleGroup.service,
|
|
534
|
-
severity: ruleGroup.severity,
|
|
535
|
-
source: ruleGroup.source,
|
|
536
|
-
message: ruleGroup.message,
|
|
537
|
-
finding
|
|
538
|
-
}))
|
|
539
|
-
)
|
|
540
|
-
);
|
|
541
|
-
var getScanDiagnostics = (result) => result.diagnostics ?? [];
|
|
542
|
-
|
|
543
|
-
// src/formatters/output.ts
|
|
544
486
|
var DEFAULT_TABLE_WIDTH = 200;
|
|
545
487
|
var MIN_COLUMN_WIDTH = 4;
|
|
546
488
|
var PREFERRED_MIN_COLUMN_WIDTH = 8;
|
|
@@ -579,8 +521,7 @@ var ruleListColumns = [
|
|
|
579
521
|
{ key: "name", header: "Name" },
|
|
580
522
|
{ key: "description", header: "Description" }
|
|
581
523
|
];
|
|
582
|
-
var
|
|
583
|
-
var OUTPUT_FORMAT_OPTION_DESCRIPTION = formatOptionDescription;
|
|
524
|
+
var OUTPUT_FORMAT_OPTION_DESCRIPTION = "Options: table: human-readable terminal output.\njson: machine-readable output for automation and downstream systems.";
|
|
584
525
|
var parseOutputFormat = (value) => {
|
|
585
526
|
if (supportedOutputFormats.includes(value)) {
|
|
586
527
|
return value;
|
|
@@ -703,7 +644,7 @@ ${renderAsciiTable(diagnosticRows, diagnosticColumns)}`
|
|
|
703
644
|
);
|
|
704
645
|
}
|
|
705
646
|
};
|
|
706
|
-
var projectFindingRows = (result) =>
|
|
647
|
+
var projectFindingRows = (result) => flattenFindings(result).map(({ finding, message, provider, ruleId, service, severity, source }) => ({
|
|
707
648
|
accountId: finding.accountId ?? "",
|
|
708
649
|
actionType: finding.actionType ?? "",
|
|
709
650
|
message,
|
|
@@ -719,7 +660,7 @@ var projectFindingRows = (result) => flattenScanResult(result).map(({ finding, m
|
|
|
719
660
|
column: finding.location?.column ?? "",
|
|
720
661
|
line: finding.location?.line ?? ""
|
|
721
662
|
}));
|
|
722
|
-
var projectDiagnosticRows = (result) =>
|
|
663
|
+
var projectDiagnosticRows = (result) => (result.diagnostics ?? []).map((diagnostic) => ({
|
|
723
664
|
message: diagnostic.message,
|
|
724
665
|
provider: diagnostic.provider,
|
|
725
666
|
region: diagnostic.region ?? "",
|
|
@@ -1077,7 +1018,8 @@ import { homedir } from "os";
|
|
|
1077
1018
|
import { join as join2 } from "path";
|
|
1078
1019
|
import {
|
|
1079
1020
|
assertSupportedAwsRegion,
|
|
1080
|
-
CloudBurnClient
|
|
1021
|
+
CloudBurnClient,
|
|
1022
|
+
resolveScanPolicy
|
|
1081
1023
|
} from "@cloudburn/sdk";
|
|
1082
1024
|
import { InvalidArgumentError as InvalidArgumentError3 } from "commander";
|
|
1083
1025
|
|
|
@@ -1096,15 +1038,6 @@ var resolveCliDebugLogger = (command) => {
|
|
|
1096
1038
|
};
|
|
1097
1039
|
};
|
|
1098
1040
|
|
|
1099
|
-
// src/policy.ts
|
|
1100
|
-
import { evaluateScanPolicy } from "@cloudburn/sdk";
|
|
1101
|
-
var hasPolicyViolation = (result, options) => {
|
|
1102
|
-
if (options.failOn !== void 0) {
|
|
1103
|
-
return evaluateScanPolicy(result, options.failOn).violated;
|
|
1104
|
-
}
|
|
1105
|
-
return options.exitCode === true ? evaluateScanPolicy(result).violated : result.policy?.violated ?? false;
|
|
1106
|
-
};
|
|
1107
|
-
|
|
1108
1041
|
// src/progress.ts
|
|
1109
1042
|
var resolveCliDiscoveryProgressLogger = (command) => {
|
|
1110
1043
|
if (isDebugEnabled(command) || process.stderr.isTTY !== true) {
|
|
@@ -1127,7 +1060,7 @@ var resolveCliDiscoveryProgressLogger = (command) => {
|
|
|
1127
1060
|
};
|
|
1128
1061
|
|
|
1129
1062
|
// src/commands/config-options.ts
|
|
1130
|
-
import {
|
|
1063
|
+
import { SEVERITIES, validateServices } from "@cloudburn/sdk";
|
|
1131
1064
|
import { InvalidArgumentError as InvalidArgumentError2 } from "commander";
|
|
1132
1065
|
var parseCommaSeparatedList = (value, itemLabel) => {
|
|
1133
1066
|
const items = value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
@@ -1146,22 +1079,25 @@ var parseSeverity = (value) => {
|
|
|
1146
1079
|
var parseRuleIdList = (value) => {
|
|
1147
1080
|
return parseCommaSeparatedList(value, "rule ID");
|
|
1148
1081
|
};
|
|
1149
|
-
var parseServiceList = (
|
|
1082
|
+
var parseServiceList = (mode) => (value) => {
|
|
1083
|
+
const services = parseCommaSeparatedList(value, "service");
|
|
1084
|
+
try {
|
|
1085
|
+
return validateServices(services, mode);
|
|
1086
|
+
} catch (err) {
|
|
1087
|
+
throw new InvalidArgumentError2(err.message);
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1150
1090
|
var parseSourceList = (value) => parseCommaSeparatedList(value, "source").map((source) => source.toLowerCase());
|
|
1151
|
-
var
|
|
1152
|
-
if (
|
|
1091
|
+
var toModeConfigOverride = (mode, options) => {
|
|
1092
|
+
if (options.enabledRules === void 0 && options.disabledRules === void 0 && options.service === void 0) {
|
|
1153
1093
|
return void 0;
|
|
1154
1094
|
}
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
`Unknown service "${invalidService}" for ${mode}. Allowed services: ${Array.from(validServices).sort().join(", ")}.`
|
|
1162
|
-
);
|
|
1163
|
-
}
|
|
1164
|
-
return services;
|
|
1095
|
+
const modeConfig = {
|
|
1096
|
+
disabledRules: options.disabledRules,
|
|
1097
|
+
enabledRules: options.enabledRules,
|
|
1098
|
+
services: options.service
|
|
1099
|
+
};
|
|
1100
|
+
return mode === "iac" ? { iac: modeConfig } : { discovery: modeConfig };
|
|
1165
1101
|
};
|
|
1166
1102
|
|
|
1167
1103
|
// src/commands/discover.ts
|
|
@@ -1178,7 +1114,6 @@ var parseCacheMode = (value) => {
|
|
|
1178
1114
|
}
|
|
1179
1115
|
throw new InvalidArgumentError3("Cache mode must be normal, refresh, or off.");
|
|
1180
1116
|
};
|
|
1181
|
-
var parseDiscoveryServiceList = (value) => validateServiceList("discovery", parseServiceList(value)) ?? [];
|
|
1182
1117
|
var describeInitializationMessage = (result) => {
|
|
1183
1118
|
const baseMessage = result.indexType === "aggregator" ? result.aggregatorAction === "promoted" ? `Promoted the existing local Resource Explorer index in ${result.aggregatorRegion} to the aggregator.` : result.aggregatorAction === "created" ? `Configured ${result.aggregatorRegion} as the Resource Explorer aggregator.` : result.coverage === "full" ? `Resource Explorer aggregator already exists in ${result.aggregatorRegion}.` : `Resource Explorer aggregator already exists in ${result.aggregatorRegion}, but only ${result.observedStatus.indexedRegionCount} of ${result.observedStatus.totalRegionCount} regions are indexed.` : result.status === "EXISTING" ? `Local Resource Explorer setup already exists in ${result.aggregatorRegion}.` : `Local Resource Explorer setup created in ${result.aggregatorRegion}.`;
|
|
1184
1119
|
const indexSummaryParts = [];
|
|
@@ -1258,18 +1193,6 @@ var resolveNestedRegionOption = (command, subcommandName) => {
|
|
|
1258
1193
|
}
|
|
1259
1194
|
return rawArgs[optionIndex + 1];
|
|
1260
1195
|
};
|
|
1261
|
-
var toDiscoveryConfigOverride = (options) => {
|
|
1262
|
-
if (options.enabledRules === void 0 && options.disabledRules === void 0 && options.service === void 0) {
|
|
1263
|
-
return void 0;
|
|
1264
|
-
}
|
|
1265
|
-
return {
|
|
1266
|
-
discovery: {
|
|
1267
|
-
disabledRules: options.disabledRules,
|
|
1268
|
-
enabledRules: options.enabledRules,
|
|
1269
|
-
services: options.service
|
|
1270
|
-
}
|
|
1271
|
-
};
|
|
1272
|
-
};
|
|
1273
1196
|
var runCommand = async (action) => {
|
|
1274
1197
|
try {
|
|
1275
1198
|
process.exitCode = await action() ?? EXIT_CODE_OK;
|
|
@@ -1299,13 +1222,13 @@ var registerDiscoverCommand = (program) => {
|
|
|
1299
1222
|
).option(
|
|
1300
1223
|
"--service <services>",
|
|
1301
1224
|
"Comma-separated services to include in the discovery rule set.",
|
|
1302
|
-
|
|
1225
|
+
parseServiceList("discovery")
|
|
1303
1226
|
).option("--exit-code", "Exit with code 1 when findings exist").option("--fail-on <severity>", "Exit with code 1 for findings at or above this severity.", parseSeverity).action(async (options, command) => {
|
|
1304
1227
|
await runCommand(async () => {
|
|
1305
1228
|
const debugLogger = resolveCliDebugLogger(command);
|
|
1306
1229
|
const onProgress = resolveCliDiscoveryProgressLogger(command);
|
|
1307
1230
|
const scanner = new CloudBurnClient({ debugLogger });
|
|
1308
|
-
const configOverride =
|
|
1231
|
+
const configOverride = toModeConfigOverride("discovery", options);
|
|
1309
1232
|
const loadedConfig = await scanner.loadConfig(options.config);
|
|
1310
1233
|
const discoveryOptions = {
|
|
1311
1234
|
cache: {
|
|
@@ -1332,10 +1255,7 @@ var registerDiscoverCommand = (program) => {
|
|
|
1332
1255
|
const output = renderResponse({ kind: "scan-result", result }, format);
|
|
1333
1256
|
process.stdout.write(`${output}
|
|
1334
1257
|
`);
|
|
1335
|
-
if (
|
|
1336
|
-
exitCode: options.exitCode,
|
|
1337
|
-
failOn: options.failOn
|
|
1338
|
-
})) {
|
|
1258
|
+
if (resolveScanPolicy(result, options).violated) {
|
|
1339
1259
|
return EXIT_CODE_POLICY_VIOLATION;
|
|
1340
1260
|
}
|
|
1341
1261
|
return EXIT_CODE_OK;
|
|
@@ -1489,42 +1409,25 @@ var registerEstimateCommand = (program) => {
|
|
|
1489
1409
|
};
|
|
1490
1410
|
|
|
1491
1411
|
// src/commands/rules-list.ts
|
|
1492
|
-
import {
|
|
1412
|
+
import { filterBuiltInRules } from "@cloudburn/sdk";
|
|
1493
1413
|
import { InvalidArgumentError as InvalidArgumentError4 } from "commander";
|
|
1494
1414
|
var VALID_SOURCES = ["discovery", "iac"];
|
|
1495
|
-
var
|
|
1496
|
-
const
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
);
|
|
1415
|
+
var parseRulesListSourceList = (value) => {
|
|
1416
|
+
const sources = parseSourceList(value);
|
|
1417
|
+
const invalidSource = sources.find((source) => !VALID_SOURCES.includes(source));
|
|
1418
|
+
if (invalidSource !== void 0) {
|
|
1419
|
+
throw new InvalidArgumentError4(`Unknown source "${invalidSource}". Allowed sources: ${VALID_SOURCES.join(", ")}.`);
|
|
1501
1420
|
}
|
|
1502
|
-
return
|
|
1503
|
-
};
|
|
1504
|
-
var parseRulesListServiceList = (value) => validateSelectedValues(parseServiceList(value), new Set(builtInRuleMetadata2.map((rule) => rule.service)), "service");
|
|
1505
|
-
var parseRulesListSourceList = (value) => validateSelectedValues(parseSourceList(value), new Set(VALID_SOURCES), "source");
|
|
1506
|
-
var filterRules = (options) => {
|
|
1507
|
-
return builtInRuleMetadata2.filter((rule) => {
|
|
1508
|
-
if (options.service !== void 0 && !options.service.includes(rule.service)) {
|
|
1509
|
-
return false;
|
|
1510
|
-
}
|
|
1511
|
-
if (options.source !== void 0 && !options.source.some((source) => rule.supports.includes(source))) {
|
|
1512
|
-
return false;
|
|
1513
|
-
}
|
|
1514
|
-
if (options.severity !== void 0 && rule.severity !== options.severity) {
|
|
1515
|
-
return false;
|
|
1516
|
-
}
|
|
1517
|
-
return true;
|
|
1518
|
-
});
|
|
1421
|
+
return sources;
|
|
1519
1422
|
};
|
|
1520
1423
|
var registerRulesListCommand = (program) => {
|
|
1521
1424
|
const rulesCommand = registerParentCommand(program, "rules", "Inspect built-in CloudBurn rules");
|
|
1522
|
-
rulesCommand.command("list").description("List built-in CloudBurn rules").option("--service <services>", "Comma-separated services to include.",
|
|
1425
|
+
rulesCommand.command("list").description("List built-in CloudBurn rules").option("--service <services>", "Comma-separated services to include.", parseServiceList()).option("--severity <severity>", "Severity to include (`high`, `medium`, `low`).", parseSeverity).option("--source <sources>", "Comma-separated sources to include (`iac`, `discovery`).", parseRulesListSourceList).action(function(options) {
|
|
1523
1426
|
const output = renderResponse(
|
|
1524
1427
|
{
|
|
1525
1428
|
kind: "rule-list",
|
|
1526
1429
|
emptyMessage: "No built-in rules are available.",
|
|
1527
|
-
rules:
|
|
1430
|
+
rules: filterBuiltInRules({ services: options.service, severity: options.severity, sources: options.source })
|
|
1528
1431
|
},
|
|
1529
1432
|
resolveOutputFormat(this, void 0, "table")
|
|
1530
1433
|
);
|
|
@@ -1534,20 +1437,7 @@ var registerRulesListCommand = (program) => {
|
|
|
1534
1437
|
};
|
|
1535
1438
|
|
|
1536
1439
|
// src/commands/scan.ts
|
|
1537
|
-
import { CloudBurnClient as CloudBurnClient2 } from "@cloudburn/sdk";
|
|
1538
|
-
var parseIaCServiceList = (value) => validateServiceList("iac", parseServiceList(value)) ?? [];
|
|
1539
|
-
var toScanConfigOverride = (options) => {
|
|
1540
|
-
if (options.enabledRules === void 0 && options.disabledRules === void 0 && options.service === void 0) {
|
|
1541
|
-
return void 0;
|
|
1542
|
-
}
|
|
1543
|
-
return {
|
|
1544
|
-
iac: {
|
|
1545
|
-
disabledRules: options.disabledRules,
|
|
1546
|
-
enabledRules: options.enabledRules,
|
|
1547
|
-
services: options.service
|
|
1548
|
-
}
|
|
1549
|
-
};
|
|
1550
|
-
};
|
|
1440
|
+
import { CloudBurnClient as CloudBurnClient2, resolveScanPolicy as resolveScanPolicy2 } from "@cloudburn/sdk";
|
|
1551
1441
|
var registerScanCommand = (program) => {
|
|
1552
1442
|
setCommandExamples(
|
|
1553
1443
|
program.command("scan").description("Run an autodetected static IaC scan").argument("[path]", "Terraform file, CloudFormation template, or directory to scan").option("--config <path>", "Explicit CloudBurn config file to load (required for config files in CI)").option(
|
|
@@ -1558,22 +1448,23 @@ var registerScanCommand = (program) => {
|
|
|
1558
1448
|
"--disabled-rules <ruleIds>",
|
|
1559
1449
|
"Comma-separated rule IDs to disable from the default AWS Core preset.",
|
|
1560
1450
|
parseRuleIdList
|
|
1561
|
-
).option(
|
|
1451
|
+
).option(
|
|
1452
|
+
"--service <services>",
|
|
1453
|
+
"Comma-separated services to include in the scan rule set.",
|
|
1454
|
+
parseServiceList("iac")
|
|
1455
|
+
).option("--exit-code", "Exit with code 1 when findings exist").option("--fail-on <severity>", "Exit with code 1 for findings at or above this severity.", parseSeverity).action(async (path, options, command) => {
|
|
1562
1456
|
try {
|
|
1563
1457
|
const debugLogger = resolveCliDebugLogger(command);
|
|
1564
1458
|
const scanner = new CloudBurnClient2({ debugLogger });
|
|
1565
|
-
const configOverride = toScanConfigOverride(options);
|
|
1566
1459
|
const loadedConfig = await scanner.loadConfig(options.config);
|
|
1567
|
-
const
|
|
1568
|
-
|
|
1460
|
+
const result = await scanner.scanStatic(path ?? process.cwd(), toModeConfigOverride("iac", options), {
|
|
1461
|
+
configPath: options.config
|
|
1462
|
+
});
|
|
1569
1463
|
const format = resolveOutputFormat(command, void 0, loadedConfig.iac.format ?? "table");
|
|
1570
1464
|
const output = renderResponse({ kind: "scan-result", result }, format);
|
|
1571
1465
|
process.stdout.write(`${output}
|
|
1572
1466
|
`);
|
|
1573
|
-
if (
|
|
1574
|
-
exitCode: options.exitCode,
|
|
1575
|
-
failOn: options.failOn
|
|
1576
|
-
})) {
|
|
1467
|
+
if (resolveScanPolicy2(result, options).violated) {
|
|
1577
1468
|
process.exitCode = EXIT_CODE_POLICY_VIOLATION;
|
|
1578
1469
|
return;
|
|
1579
1470
|
}
|
|
@@ -1604,7 +1495,7 @@ var isCliEntrypoint = (moduleUrl, argvEntry = process.argv[1]) => {
|
|
|
1604
1495
|
};
|
|
1605
1496
|
var createProgram = () => {
|
|
1606
1497
|
const program = createCliCommand();
|
|
1607
|
-
program.name("cloudburn").usage("[command]").description("Know what you spend. Fix what you waste.").version("0.18.
|
|
1498
|
+
program.name("cloudburn").usage("[command]").description("Know what you spend. Fix what you waste.").version("0.18.9").option("--debug", "Write execution trace messages to stderr").option("--format <format>", OUTPUT_FORMAT_OPTION_DESCRIPTION, parseOutputFormat);
|
|
1608
1499
|
configureCliHelp(program);
|
|
1609
1500
|
program.exitOverride();
|
|
1610
1501
|
registerCompletionCommand(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cloudburn",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.9",
|
|
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.
|
|
23
|
+
"@cloudburn/sdk": "0.38.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@biomejs/biome": "^2.5.12",
|