cloudburn 0.3.1 → 0.4.1

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 +10 -0
  2. package/dist/cli.js +55 -11
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -14,6 +14,16 @@ npm install -g cloudburn
14
14
  cloudburn
15
15
  ```
16
16
 
17
+ Static scans auto-detect Terraform and CloudFormation from the file or
18
+ directory path you pass to `cloudburn scan`.
19
+
20
+ ```sh
21
+ cloudburn scan ./main.tf
22
+ cloudburn scan ./template.yaml
23
+ cloudburn scan ./iac
24
+ cloudburn scan --live
25
+ ```
26
+
17
27
  `cloudburn scan --format json` emits the lean canonical grouped result:
18
28
 
19
29
  ```json
package/dist/cli.js CHANGED
@@ -58,6 +58,35 @@ import { InvalidArgumentError } from "commander";
58
58
  // src/exit-codes.ts
59
59
  var EXIT_CODE_OK = 0;
60
60
  var EXIT_CODE_POLICY_VIOLATION = 1;
61
+ var EXIT_CODE_RUNTIME_ERROR = 2;
62
+
63
+ // src/formatters/error.ts
64
+ var formatError = (err) => {
65
+ const envelope = { error: categorize(err) };
66
+ return JSON.stringify(envelope, null, 2);
67
+ };
68
+ var categorize = (err) => {
69
+ if (!(err instanceof Error)) {
70
+ return { code: "RUNTIME_ERROR", message: "An unexpected error occurred." };
71
+ }
72
+ if (err.name === "CredentialsProviderError" || err.name === "ExpiredTokenException") {
73
+ return {
74
+ code: "CREDENTIALS_ERROR",
75
+ message: "AWS credentials not found or expired. Run 'aws sts get-caller-identity' to verify your session."
76
+ };
77
+ }
78
+ if (err.name.includes("AccessDenied")) {
79
+ return {
80
+ code: "ACCESS_DENIED",
81
+ message: "Insufficient AWS permissions. Check your IAM role or policy."
82
+ };
83
+ }
84
+ if (err.code === "ENOENT") {
85
+ const path = err.path ?? "unknown";
86
+ return { code: "PATH_NOT_FOUND", message: `Path not found: ${path}` };
87
+ }
88
+ return { code: "RUNTIME_ERROR", message: err.message || "An unexpected error occurred." };
89
+ };
61
90
 
62
91
  // src/formatters/json.ts
63
92
  var formatJson = (result) => JSON.stringify(result, null, 2);
@@ -148,25 +177,40 @@ var formatters = {
148
177
  table: formatTable
149
178
  };
150
179
  var registerScanCommand = (program) => {
151
- program.command("scan [path]").description("Run static IaC scan or live AWS scan").option("--live", "Run live AWS scan").option("--format <format>", "Output format: table|json|sarif", parseScanFormat, "table").option("--exit-code", "Exit with code 1 when findings exist").action(async (path, options) => {
152
- const scanner = new CloudBurnScanner();
153
- const result = options.live ? await scanner.scanLive() : await scanner.scanStatic(path ?? process.cwd());
154
- const format = formatters[options.format ?? "table"];
155
- const output = format(result);
156
- process.stdout.write(`${output}
180
+ program.command("scan").description("Run an autodetected static IaC scan, or a live AWS scan with --live").argument("[path]", "Terraform file, CloudFormation template, or directory to scan").option("--live", "Run live AWS scan").option("--format <format>", "Output format: table|json|sarif", parseScanFormat, "table").option("--exit-code", "Exit with code 1 when findings exist").addHelpText(
181
+ "after",
182
+ `
183
+ Examples:
184
+ cloudburn scan ./main.tf
185
+ cloudburn scan ./template.yaml
186
+ cloudburn scan ./iac
187
+ cloudburn scan --live
188
+ `
189
+ ).action(async (path, options) => {
190
+ try {
191
+ const scanner = new CloudBurnScanner();
192
+ const result = options.live ? await scanner.scanLive() : await scanner.scanStatic(path ?? process.cwd());
193
+ const format = formatters[options.format ?? "table"];
194
+ const output = format(result);
195
+ process.stdout.write(`${output}
157
196
  `);
158
- if (options.exitCode && countScanResultFindings(result) > 0) {
159
- process.exitCode = EXIT_CODE_POLICY_VIOLATION;
160
- return;
197
+ if (options.exitCode && countScanResultFindings(result) > 0) {
198
+ process.exitCode = EXIT_CODE_POLICY_VIOLATION;
199
+ return;
200
+ }
201
+ process.exitCode = EXIT_CODE_OK;
202
+ } catch (err) {
203
+ process.stderr.write(`${formatError(err)}
204
+ `);
205
+ process.exitCode = EXIT_CODE_RUNTIME_ERROR;
161
206
  }
162
- process.exitCode = EXIT_CODE_OK;
163
207
  });
164
208
  };
165
209
 
166
210
  // src/cli.ts
167
211
  var createProgram = () => {
168
212
  const program = new Command();
169
- program.name("cloudburn").description("Know what you spend. Fix what you waste.").version("0.0.0");
213
+ program.name("cloudburn").description("Know what you spend. Fix what you waste.").version("0.4.1");
170
214
  registerScanCommand(program);
171
215
  registerInitCommand(program);
172
216
  registerRulesListCommand(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudburn",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "Cloudburn CLI for cloud cost optimization",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,7 +11,7 @@
11
11
  ],
12
12
  "dependencies": {
13
13
  "commander": "^13.1.0",
14
- "@cloudburn/sdk": "0.6.0"
14
+ "@cloudburn/sdk": "0.7.0"
15
15
  },
16
16
  "devDependencies": {
17
17
  "@biomejs/biome": "^2.4.6",