infra-cost 0.2.0 → 0.2.2
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/bin/index.js +1 -1
- package/dist/demo/{test-enhanced-ui.js → test-enhanced-ui.cjs} +126 -91
- package/dist/demo/test-enhanced-ui.cjs.map +1 -0
- package/dist/demo/{test-multi-cloud-dashboard.js → test-multi-cloud-dashboard.cjs} +176 -160
- package/dist/demo/test-multi-cloud-dashboard.cjs.map +1 -0
- package/dist/{index.js → index.cjs} +4495 -4523
- package/dist/index.cjs.map +1 -0
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -1,13 +1,46 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
2
29
|
|
|
3
30
|
// src/demo/test-enhanced-ui.ts
|
|
4
|
-
|
|
31
|
+
var test_enhanced_ui_exports = {};
|
|
32
|
+
__export(test_enhanced_ui_exports, {
|
|
33
|
+
testEnhancedUI: () => testEnhancedUI,
|
|
34
|
+
testPDFGeneration: () => testPDFGeneration
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(test_enhanced_ui_exports);
|
|
37
|
+
var import_chalk2 = __toESM(require("chalk"), 1);
|
|
5
38
|
|
|
6
39
|
// src/visualization/terminal-ui.ts
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
40
|
+
var import_cli_table3 = __toESM(require("cli-table3"), 1);
|
|
41
|
+
var import_chalk = __toESM(require("chalk"), 1);
|
|
42
|
+
var import_cli_progress = __toESM(require("cli-progress"), 1);
|
|
43
|
+
var import_moment = __toESM(require("moment"), 1);
|
|
11
44
|
var TerminalUIEngine = class {
|
|
12
45
|
constructor() {
|
|
13
46
|
this.progressBar = null;
|
|
@@ -16,8 +49,8 @@ var TerminalUIEngine = class {
|
|
|
16
49
|
* Creates a formatted table with enhanced styling
|
|
17
50
|
*/
|
|
18
51
|
createTable(columns, rows) {
|
|
19
|
-
const table = new
|
|
20
|
-
head: columns.map((col) =>
|
|
52
|
+
const table = new import_cli_table3.default({
|
|
53
|
+
head: columns.map((col) => import_chalk.default.bold(col.header)),
|
|
21
54
|
colWidths: columns.map((col) => col.width || 20),
|
|
22
55
|
colAligns: columns.map((col) => col.align || "left"),
|
|
23
56
|
style: {
|
|
@@ -48,7 +81,7 @@ var TerminalUIEngine = class {
|
|
|
48
81
|
const value = Object.values(row)[index];
|
|
49
82
|
const colorKey = col.color;
|
|
50
83
|
if (colorKey && typeof value === "string") {
|
|
51
|
-
return
|
|
84
|
+
return import_chalk.default[colorKey](value);
|
|
52
85
|
}
|
|
53
86
|
return String(value);
|
|
54
87
|
});
|
|
@@ -67,7 +100,7 @@ var TerminalUIEngine = class {
|
|
|
67
100
|
compact: false
|
|
68
101
|
}) {
|
|
69
102
|
const { totals, totalsByService } = costBreakdown;
|
|
70
|
-
let output = "\n" +
|
|
103
|
+
let output = "\n" + import_chalk.default.bold.cyan("\u{1F4B0} Cost Analysis Summary") + "\n";
|
|
71
104
|
output += "\u2550".repeat(50) + "\n\n";
|
|
72
105
|
const summaryColumns = [
|
|
73
106
|
{ header: "Period", width: 15, align: "left", color: "cyan" },
|
|
@@ -97,7 +130,7 @@ var TerminalUIEngine = class {
|
|
|
97
130
|
}
|
|
98
131
|
];
|
|
99
132
|
output += this.createTable(summaryColumns, summaryRows) + "\n\n";
|
|
100
|
-
output +=
|
|
133
|
+
output += import_chalk.default.bold.cyan("\u{1F4CA} Service Breakdown (This Month)") + "\n";
|
|
101
134
|
output += "\u2550".repeat(50) + "\n\n";
|
|
102
135
|
const allServiceEntries = Object.entries(totalsByService.thisMonth);
|
|
103
136
|
const significantServices = allServiceEntries.filter(([_, cost]) => cost > 0.01).sort(([, a], [, b]) => b - a);
|
|
@@ -107,7 +140,7 @@ var TerminalUIEngine = class {
|
|
|
107
140
|
const hiddenServices = allServiceEntries.length - maxDisplay;
|
|
108
141
|
const hiddenCost = significantServices.slice(maxDisplay).reduce((sum, [_, cost]) => sum + cost, 0);
|
|
109
142
|
if (hiddenCost > 0) {
|
|
110
|
-
output +=
|
|
143
|
+
output += import_chalk.default.gray(`Showing top ${maxDisplay} of ${allServiceEntries.length} services `) + import_chalk.default.gray(`(${hiddenServices} services with $${hiddenCost.toFixed(2)} hidden)
|
|
111
144
|
|
|
112
145
|
`);
|
|
113
146
|
}
|
|
@@ -141,9 +174,9 @@ var TerminalUIEngine = class {
|
|
|
141
174
|
currency: "USD"
|
|
142
175
|
}) {
|
|
143
176
|
if (!trendData || trendData.length === 0) {
|
|
144
|
-
return
|
|
177
|
+
return import_chalk.default.red("No trend data available");
|
|
145
178
|
}
|
|
146
|
-
let output = "\n" +
|
|
179
|
+
let output = "\n" + import_chalk.default.bold.cyan("\u{1F4C8} Cost Trend Analysis") + "\n";
|
|
147
180
|
output += "\u2550".repeat(50) + "\n\n";
|
|
148
181
|
const maxCost = Math.max(...trendData.map((d) => d.actualCost));
|
|
149
182
|
const minCost = Math.min(...trendData.map((d) => d.actualCost));
|
|
@@ -153,7 +186,7 @@ var TerminalUIEngine = class {
|
|
|
153
186
|
const barLength = Math.round(normalizedValue * options.width);
|
|
154
187
|
const bar = "\u2588".repeat(barLength) + "\u2591".repeat(options.width - barLength);
|
|
155
188
|
const coloredBar = this.colorizeBar(bar, normalizedValue, options.colorThreshold);
|
|
156
|
-
const period =
|
|
189
|
+
const period = (0, import_moment.default)(data.period).format("MMM YYYY");
|
|
157
190
|
const cost = this.formatCurrency(data.actualCost, options.currency);
|
|
158
191
|
const change = data.changeFromPrevious ? this.formatChangeIndicator(data.changeFromPrevious.percentage) : "";
|
|
159
192
|
output += `${period.padEnd(10)} ${coloredBar} ${cost.padStart(10)} ${change}
|
|
@@ -171,8 +204,8 @@ var TerminalUIEngine = class {
|
|
|
171
204
|
if (this.progressBar) {
|
|
172
205
|
this.progressBar.stop();
|
|
173
206
|
}
|
|
174
|
-
this.progressBar = new
|
|
175
|
-
format: `${
|
|
207
|
+
this.progressBar = new import_cli_progress.default.SingleBar({
|
|
208
|
+
format: `${import_chalk.default.cyan(label)} ${import_chalk.default.cyan("[")}${import_chalk.default.yellow("{bar}")}${import_chalk.default.cyan("]")} {percentage}% | ETA: {eta}s | {value}/{total}`,
|
|
176
209
|
barCompleteChar: "\u2588",
|
|
177
210
|
barIncompleteChar: "\u2591",
|
|
178
211
|
hideCursor: true
|
|
@@ -201,14 +234,14 @@ var TerminalUIEngine = class {
|
|
|
201
234
|
*/
|
|
202
235
|
createAnomalyAlert(anomalies) {
|
|
203
236
|
if (anomalies.length === 0) {
|
|
204
|
-
return
|
|
237
|
+
return import_chalk.default.green("\u2705 No cost anomalies detected");
|
|
205
238
|
}
|
|
206
|
-
let output = "\n" +
|
|
239
|
+
let output = "\n" + import_chalk.default.bold.red("\u{1F6A8} Cost Anomalies Detected") + "\n";
|
|
207
240
|
output += "\u2550".repeat(50) + "\n\n";
|
|
208
241
|
anomalies.forEach((anomaly) => {
|
|
209
242
|
const severityColor = this.getSeverityColor(anomaly.severity);
|
|
210
243
|
const icon = this.getSeverityIcon(anomaly.severity);
|
|
211
|
-
output +=
|
|
244
|
+
output += import_chalk.default[severityColor](`${icon} ${anomaly.date}
|
|
212
245
|
`);
|
|
213
246
|
output += ` Expected: ${this.formatCurrency(anomaly.expectedCost, "USD")}
|
|
214
247
|
`;
|
|
@@ -217,7 +250,7 @@ var TerminalUIEngine = class {
|
|
|
217
250
|
output += ` Deviation: ${anomaly.deviation > 0 ? "+" : ""}${anomaly.deviation.toFixed(1)}%
|
|
218
251
|
`;
|
|
219
252
|
if (anomaly.description) {
|
|
220
|
-
output += ` ${
|
|
253
|
+
output += ` ${import_chalk.default.gray(anomaly.description)}
|
|
221
254
|
`;
|
|
222
255
|
}
|
|
223
256
|
output += "\n";
|
|
@@ -230,14 +263,14 @@ var TerminalUIEngine = class {
|
|
|
230
263
|
createHeader(title, subtitle) {
|
|
231
264
|
const width = 60;
|
|
232
265
|
let output = "\n";
|
|
233
|
-
output +=
|
|
266
|
+
output += import_chalk.default.cyan("\u250C" + "\u2500".repeat(width - 2) + "\u2510") + "\n";
|
|
234
267
|
const titlePadding = Math.floor((width - title.length - 4) / 2);
|
|
235
|
-
output +=
|
|
268
|
+
output += import_chalk.default.cyan("\u2502") + " ".repeat(titlePadding) + import_chalk.default.bold.white(title) + " ".repeat(width - title.length - titlePadding - 2) + import_chalk.default.cyan("\u2502") + "\n";
|
|
236
269
|
if (subtitle) {
|
|
237
270
|
const subtitlePadding = Math.floor((width - subtitle.length - 4) / 2);
|
|
238
|
-
output +=
|
|
271
|
+
output += import_chalk.default.cyan("\u2502") + " ".repeat(subtitlePadding) + import_chalk.default.gray(subtitle) + " ".repeat(width - subtitle.length - subtitlePadding - 2) + import_chalk.default.cyan("\u2502") + "\n";
|
|
239
272
|
}
|
|
240
|
-
output +=
|
|
273
|
+
output += import_chalk.default.cyan("\u2514" + "\u2500".repeat(width - 2) + "\u2518") + "\n\n";
|
|
241
274
|
return output;
|
|
242
275
|
}
|
|
243
276
|
// Helper methods
|
|
@@ -255,42 +288,42 @@ var TerminalUIEngine = class {
|
|
|
255
288
|
const change = (current - previous) / previous * 100;
|
|
256
289
|
const changeStr = `${change >= 0 ? "+" : ""}${change.toFixed(1)}%`;
|
|
257
290
|
if (change > 0) {
|
|
258
|
-
return
|
|
291
|
+
return import_chalk.default.red(`\u2197 ${changeStr}`);
|
|
259
292
|
} else if (change < 0) {
|
|
260
|
-
return
|
|
293
|
+
return import_chalk.default.green(`\u2198 ${changeStr}`);
|
|
261
294
|
} else {
|
|
262
|
-
return
|
|
295
|
+
return import_chalk.default.gray("\u2192 0.0%");
|
|
263
296
|
}
|
|
264
297
|
}
|
|
265
298
|
getTrendIndicator(current, previous) {
|
|
266
299
|
if (previous === 0)
|
|
267
|
-
return
|
|
300
|
+
return import_chalk.default.gray("\u2500");
|
|
268
301
|
const change = (current - previous) / previous * 100;
|
|
269
302
|
if (change > 10)
|
|
270
|
-
return
|
|
303
|
+
return import_chalk.default.red("\u2197\u2197");
|
|
271
304
|
if (change > 0)
|
|
272
|
-
return
|
|
305
|
+
return import_chalk.default.yellow("\u2197");
|
|
273
306
|
if (change < -10)
|
|
274
|
-
return
|
|
307
|
+
return import_chalk.default.green("\u2198\u2198");
|
|
275
308
|
if (change < 0)
|
|
276
|
-
return
|
|
277
|
-
return
|
|
309
|
+
return import_chalk.default.green("\u2198");
|
|
310
|
+
return import_chalk.default.gray("\u2192");
|
|
278
311
|
}
|
|
279
312
|
colorizeBar(bar, normalizedValue, threshold) {
|
|
280
313
|
const thresholdValue = threshold || 0.7;
|
|
281
314
|
if (normalizedValue > thresholdValue) {
|
|
282
|
-
return
|
|
315
|
+
return import_chalk.default.red(bar);
|
|
283
316
|
} else if (normalizedValue > 0.4) {
|
|
284
|
-
return
|
|
317
|
+
return import_chalk.default.yellow(bar);
|
|
285
318
|
} else {
|
|
286
|
-
return
|
|
319
|
+
return import_chalk.default.green(bar);
|
|
287
320
|
}
|
|
288
321
|
}
|
|
289
322
|
formatChangeIndicator(percentage) {
|
|
290
323
|
const indicator = percentage >= 0 ? "\u2197" : "\u2198";
|
|
291
324
|
const color = percentage >= 0 ? "red" : "green";
|
|
292
325
|
const sign = percentage >= 0 ? "+" : "";
|
|
293
|
-
return
|
|
326
|
+
return import_chalk.default[color](`${indicator} ${sign}${percentage.toFixed(1)}%`);
|
|
294
327
|
}
|
|
295
328
|
getSeverityColor(severity) {
|
|
296
329
|
switch (severity.toLowerCase()) {
|
|
@@ -638,10 +671,10 @@ var DemoDataGenerator = class {
|
|
|
638
671
|
};
|
|
639
672
|
|
|
640
673
|
// src/exporters/pdf-exporter.ts
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
674
|
+
var import_puppeteer = __toESM(require("puppeteer"), 1);
|
|
675
|
+
var import_fs = require("fs");
|
|
676
|
+
var import_path = require("path");
|
|
677
|
+
var import_moment2 = __toESM(require("moment"), 1);
|
|
645
678
|
var PDFExporter = class {
|
|
646
679
|
constructor(options = {}) {
|
|
647
680
|
this.browser = null;
|
|
@@ -664,9 +697,9 @@ var PDFExporter = class {
|
|
|
664
697
|
try {
|
|
665
698
|
await this.initializeBrowser();
|
|
666
699
|
const html = this.generateAuditHTML(data);
|
|
667
|
-
const filename = this.options.filename || `infra-cost-audit-${
|
|
700
|
+
const filename = this.options.filename || `infra-cost-audit-${(0, import_moment2.default)(data.generatedAt).format("YYYY-MM-DD-HHmm")}.pdf`;
|
|
668
701
|
const outputPath = this.ensureOutputDirectory();
|
|
669
|
-
const fullPath = join(outputPath, filename);
|
|
702
|
+
const fullPath = (0, import_path.join)(outputPath, filename);
|
|
670
703
|
const page = await this.browser.newPage();
|
|
671
704
|
await page.setContent(html, { waitUntil: "networkidle0" });
|
|
672
705
|
await page.pdf({
|
|
@@ -730,7 +763,7 @@ var PDFExporter = class {
|
|
|
730
763
|
this.options.includeCharts = true;
|
|
731
764
|
this.options.includeSummary = true;
|
|
732
765
|
this.options.includeRecommendations = true;
|
|
733
|
-
const filename = `infra-cost-executive-summary-${
|
|
766
|
+
const filename = `infra-cost-executive-summary-${(0, import_moment2.default)(data.generatedAt).format("YYYY-MM-DD")}.pdf`;
|
|
734
767
|
this.options.filename = filename;
|
|
735
768
|
return this.generateAuditReport(data);
|
|
736
769
|
}
|
|
@@ -782,12 +815,12 @@ var PDFExporter = class {
|
|
|
782
815
|
<strong>Cloud Provider:</strong> ${this.getProviderDisplayName(data.accountInfo.provider)}
|
|
783
816
|
</div>
|
|
784
817
|
<div class="info-item">
|
|
785
|
-
<strong>Report Generated:</strong> ${
|
|
818
|
+
<strong>Report Generated:</strong> ${(0, import_moment2.default)(data.generatedAt).format("MMMM Do YYYY, h:mm:ss a")}
|
|
786
819
|
</div>
|
|
787
820
|
<div class="info-item">
|
|
788
821
|
<strong>Report Period:</strong>
|
|
789
|
-
${
|
|
790
|
-
${
|
|
822
|
+
${(0, import_moment2.default)(data.reportPeriod.start).format("MMM DD, YYYY")} -
|
|
823
|
+
${(0, import_moment2.default)(data.reportPeriod.end).format("MMM DD, YYYY")}
|
|
791
824
|
</div>
|
|
792
825
|
</div>
|
|
793
826
|
</div>
|
|
@@ -868,7 +901,7 @@ var PDFExporter = class {
|
|
|
868
901
|
<h3>Key Performance Indicators</h3>
|
|
869
902
|
<div class="metrics-grid">
|
|
870
903
|
<div class="metric">
|
|
871
|
-
<div class="metric-value">${this.formatCurrency(data.costBreakdown.totals.thisMonth /
|
|
904
|
+
<div class="metric-value">${this.formatCurrency(data.costBreakdown.totals.thisMonth / (0, import_moment2.default)().date())}</div>
|
|
872
905
|
<div class="metric-label">Avg Daily Spend</div>
|
|
873
906
|
</div>
|
|
874
907
|
<div class="metric">
|
|
@@ -1098,7 +1131,7 @@ var PDFExporter = class {
|
|
|
1098
1131
|
${anomalies.map((anomaly) => `
|
|
1099
1132
|
<div class="anomaly-card severity-${anomaly.severity.toLowerCase()}">
|
|
1100
1133
|
<div class="anomaly-header">
|
|
1101
|
-
<h4>${
|
|
1134
|
+
<h4>${(0, import_moment2.default)(anomaly.date).format("MMMM DD, YYYY")}</h4>
|
|
1102
1135
|
<span class="severity-badge ${anomaly.severity.toLowerCase()}">${anomaly.severity}</span>
|
|
1103
1136
|
</div>
|
|
1104
1137
|
<div class="anomaly-details">
|
|
@@ -1205,7 +1238,7 @@ var PDFExporter = class {
|
|
|
1205
1238
|
<table class="metadata-table">
|
|
1206
1239
|
<tr>
|
|
1207
1240
|
<td>Report Generated:</td>
|
|
1208
|
-
<td>${
|
|
1241
|
+
<td>${(0, import_moment2.default)(data.generatedAt).format("MMMM Do YYYY, h:mm:ss a")}</td>
|
|
1209
1242
|
</tr>
|
|
1210
1243
|
<tr>
|
|
1211
1244
|
<td>Tool Version:</td>
|
|
@@ -1221,7 +1254,7 @@ var PDFExporter = class {
|
|
|
1221
1254
|
</tr>
|
|
1222
1255
|
<tr>
|
|
1223
1256
|
<td>Analysis Period:</td>
|
|
1224
|
-
<td>${
|
|
1257
|
+
<td>${(0, import_moment2.default)(data.reportPeriod.start).format("MMM DD, YYYY")} - ${(0, import_moment2.default)(data.reportPeriod.end).format("MMM DD, YYYY")}</td>
|
|
1225
1258
|
</tr>
|
|
1226
1259
|
</table>
|
|
1227
1260
|
</div>
|
|
@@ -1462,13 +1495,13 @@ var PDFExporter = class {
|
|
|
1462
1495
|
<div style="display: flex; justify-content: space-between; width: 100%; align-items: center;">
|
|
1463
1496
|
<span>Generated by infra-cost v0.1.0</span>
|
|
1464
1497
|
<span>Page <span class="pageNumber"></span> of <span class="totalPages"></span></span>
|
|
1465
|
-
<span>${
|
|
1498
|
+
<span>${(0, import_moment2.default)().format("YYYY-MM-DD HH:mm")}</span>
|
|
1466
1499
|
</div>
|
|
1467
1500
|
</div>`;
|
|
1468
1501
|
}
|
|
1469
1502
|
async initializeBrowser() {
|
|
1470
1503
|
if (!this.browser) {
|
|
1471
|
-
this.browser = await
|
|
1504
|
+
this.browser = await import_puppeteer.default.launch({
|
|
1472
1505
|
headless: true,
|
|
1473
1506
|
args: ["--no-sandbox", "--disable-setuid-sandbox"]
|
|
1474
1507
|
});
|
|
@@ -1482,8 +1515,8 @@ var PDFExporter = class {
|
|
|
1482
1515
|
}
|
|
1483
1516
|
ensureOutputDirectory() {
|
|
1484
1517
|
const outputPath = this.options.outputPath;
|
|
1485
|
-
if (!existsSync(outputPath)) {
|
|
1486
|
-
mkdirSync(outputPath, { recursive: true });
|
|
1518
|
+
if (!(0, import_fs.existsSync)(outputPath)) {
|
|
1519
|
+
(0, import_fs.mkdirSync)(outputPath, { recursive: true });
|
|
1487
1520
|
}
|
|
1488
1521
|
return outputPath;
|
|
1489
1522
|
}
|
|
@@ -1526,14 +1559,15 @@ var PDFExporter = class {
|
|
|
1526
1559
|
};
|
|
1527
1560
|
|
|
1528
1561
|
// src/demo/test-enhanced-ui.ts
|
|
1562
|
+
var import_meta = {};
|
|
1529
1563
|
async function testEnhancedUI() {
|
|
1530
|
-
console.log(
|
|
1564
|
+
console.log(import_chalk2.default.bold.cyan("\u{1F9EA} Testing Enhanced Terminal UI Features\n"));
|
|
1531
1565
|
const ui = new TerminalUIEngine();
|
|
1532
|
-
console.log(
|
|
1566
|
+
console.log(import_chalk2.default.bold.yellow("Test 1: Enhanced Header"));
|
|
1533
1567
|
console.log("\u2500".repeat(50));
|
|
1534
1568
|
const header = ui.createHeader("\u{1F680} Infrastructure Cost Analysis", "Demo Production Account");
|
|
1535
1569
|
console.log(header);
|
|
1536
|
-
console.log(
|
|
1570
|
+
console.log(import_chalk2.default.bold.yellow("Test 2: Rich Cost Breakdown Table"));
|
|
1537
1571
|
console.log("\u2500".repeat(50));
|
|
1538
1572
|
const costBreakdown = DemoDataGenerator.generateCostBreakdown();
|
|
1539
1573
|
const costTable = ui.createCostTable(costBreakdown, {
|
|
@@ -1543,7 +1577,7 @@ async function testEnhancedUI() {
|
|
|
1543
1577
|
compact: false
|
|
1544
1578
|
});
|
|
1545
1579
|
console.log(costTable);
|
|
1546
|
-
console.log(
|
|
1580
|
+
console.log(import_chalk2.default.bold.yellow("Test 3: ASCII Trend Chart"));
|
|
1547
1581
|
console.log("\u2500".repeat(50));
|
|
1548
1582
|
const trendAnalysis = DemoDataGenerator.generateTrendAnalysis();
|
|
1549
1583
|
if (trendAnalysis.trendData) {
|
|
@@ -1555,12 +1589,12 @@ async function testEnhancedUI() {
|
|
|
1555
1589
|
});
|
|
1556
1590
|
console.log(trendChart);
|
|
1557
1591
|
}
|
|
1558
|
-
console.log(
|
|
1592
|
+
console.log(import_chalk2.default.bold.yellow("Test 4: Cost Anomaly Alerts"));
|
|
1559
1593
|
console.log("\u2500".repeat(50));
|
|
1560
1594
|
const anomalies = DemoDataGenerator.generateCostAnomalies();
|
|
1561
1595
|
const anomalyAlert = ui.createAnomalyAlert(anomalies);
|
|
1562
1596
|
console.log(anomalyAlert);
|
|
1563
|
-
console.log(
|
|
1597
|
+
console.log(import_chalk2.default.bold.yellow("Test 5: Progress Indicators"));
|
|
1564
1598
|
console.log("\u2500".repeat(50));
|
|
1565
1599
|
ui.startProgress("Processing cost analysis", 100);
|
|
1566
1600
|
for (let i = 0; i <= 100; i += 20) {
|
|
@@ -1568,34 +1602,34 @@ async function testEnhancedUI() {
|
|
|
1568
1602
|
ui.updateProgress(i, { step: `Processing step ${i / 20 + 1}/6` });
|
|
1569
1603
|
}
|
|
1570
1604
|
ui.stopProgress();
|
|
1571
|
-
console.log(
|
|
1572
|
-
console.log(
|
|
1605
|
+
console.log(import_chalk2.default.green("\u2705 Processing completed!\n"));
|
|
1606
|
+
console.log(import_chalk2.default.bold.yellow("Test 6: Executive Summary Format"));
|
|
1573
1607
|
console.log("\u2500".repeat(50));
|
|
1574
1608
|
const recommendations = DemoDataGenerator.generateRecommendations();
|
|
1575
1609
|
const totalSavings = recommendations.reduce((sum, rec) => sum + rec.potentialSavings.amount, 0);
|
|
1576
|
-
console.log("\n" +
|
|
1610
|
+
console.log("\n" + import_chalk2.default.bold.cyan("\u{1F3AF} Key Performance Indicators"));
|
|
1577
1611
|
console.log("\u2550".repeat(50));
|
|
1578
|
-
console.log(`Monthly Spend: ${
|
|
1579
|
-
console.log(`Cost Change: ${costBreakdown.totals.thisMonth > costBreakdown.totals.lastMonth ?
|
|
1580
|
-
console.log(`Optimization Potential: ${
|
|
1581
|
-
console.log(`Active Recommendations: ${
|
|
1582
|
-
console.log("\n" +
|
|
1612
|
+
console.log(`Monthly Spend: ${import_chalk2.default.yellow("$" + costBreakdown.totals.thisMonth.toFixed(2))}`);
|
|
1613
|
+
console.log(`Cost Change: ${costBreakdown.totals.thisMonth > costBreakdown.totals.lastMonth ? import_chalk2.default.red("\u2197 +" + ((costBreakdown.totals.thisMonth - costBreakdown.totals.lastMonth) / costBreakdown.totals.lastMonth * 100).toFixed(1) + "%") : import_chalk2.default.green("\u2198 " + ((costBreakdown.totals.thisMonth - costBreakdown.totals.lastMonth) / costBreakdown.totals.lastMonth * 100).toFixed(1) + "%")}`);
|
|
1614
|
+
console.log(`Optimization Potential: ${import_chalk2.default.green("$" + totalSavings.toFixed(2))}`);
|
|
1615
|
+
console.log(`Active Recommendations: ${import_chalk2.default.cyan(recommendations.length.toString())}`);
|
|
1616
|
+
console.log("\n" + import_chalk2.default.bold.cyan("\u{1F4A1} Top Cost Optimization Recommendations"));
|
|
1583
1617
|
console.log("\u2550".repeat(60));
|
|
1584
1618
|
recommendations.slice(0, 3).forEach((rec, index) => {
|
|
1585
1619
|
console.log(`
|
|
1586
|
-
${index + 1}. ${
|
|
1620
|
+
${index + 1}. ${import_chalk2.default.bold(rec.title)}`);
|
|
1587
1621
|
console.log(` ${rec.description}`);
|
|
1588
|
-
console.log(` \u{1F4B0} Potential savings: ${
|
|
1589
|
-
console.log(` \u{1F3AF} Priority: ${
|
|
1590
|
-
console.log(` \u{1F527} Effort: ${
|
|
1622
|
+
console.log(` \u{1F4B0} Potential savings: ${import_chalk2.default.green("$" + rec.potentialSavings.amount.toFixed(2))} ${rec.potentialSavings.timeframe.toLowerCase()}`);
|
|
1623
|
+
console.log(` \u{1F3AF} Priority: ${import_chalk2.default[rec.priority === "HIGH" ? "red" : rec.priority === "MEDIUM" ? "yellow" : "cyan"](rec.priority)}`);
|
|
1624
|
+
console.log(` \u{1F527} Effort: ${import_chalk2.default.gray(rec.effort)}`);
|
|
1591
1625
|
});
|
|
1592
|
-
console.log("\n" +
|
|
1593
|
-
console.log(
|
|
1594
|
-
console.log(
|
|
1626
|
+
console.log("\n" + import_chalk2.default.gray("\u2501".repeat(70)));
|
|
1627
|
+
console.log(import_chalk2.default.gray("\u{1F4A1} Demo completed successfully! All enhanced UI features are working."));
|
|
1628
|
+
console.log(import_chalk2.default.gray("\u{1F4CA} Use --trend, --audit, or --executive-summary with real data"));
|
|
1595
1629
|
return true;
|
|
1596
1630
|
}
|
|
1597
1631
|
async function testPDFGeneration() {
|
|
1598
|
-
console.log("\n" +
|
|
1632
|
+
console.log("\n" + import_chalk2.default.bold.cyan("\u{1F4C4} Testing PDF Generation"));
|
|
1599
1633
|
console.log("\u2500".repeat(50));
|
|
1600
1634
|
try {
|
|
1601
1635
|
const pdfExporter = new PDFExporter({
|
|
@@ -1624,39 +1658,40 @@ async function testPDFGeneration() {
|
|
|
1624
1658
|
}
|
|
1625
1659
|
};
|
|
1626
1660
|
const pdfPath = await pdfExporter.generateAuditReport(auditData);
|
|
1627
|
-
console.log(
|
|
1661
|
+
console.log(import_chalk2.default.green(`\u2705 Demo PDF report generated: ${pdfPath}`));
|
|
1628
1662
|
return true;
|
|
1629
1663
|
} catch (error) {
|
|
1630
|
-
console.log(
|
|
1631
|
-
console.log(
|
|
1664
|
+
console.log(import_chalk2.default.yellow(`\u26A0\uFE0F PDF generation test skipped: ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
1665
|
+
console.log(import_chalk2.default.gray(" (This is expected in environments without browser support)"));
|
|
1632
1666
|
return false;
|
|
1633
1667
|
}
|
|
1634
1668
|
}
|
|
1635
1669
|
async function main() {
|
|
1636
1670
|
try {
|
|
1637
|
-
console.log(
|
|
1638
|
-
console.log(
|
|
1671
|
+
console.log(import_chalk2.default.bold.blue("\u{1F680} Enhanced infra-cost UI Testing Suite"));
|
|
1672
|
+
console.log(import_chalk2.default.gray("Testing all new features with realistic demo data\n"));
|
|
1639
1673
|
const uiTestResult = await testEnhancedUI();
|
|
1640
1674
|
const pdfTestResult = await testPDFGeneration();
|
|
1641
|
-
console.log("\n" +
|
|
1642
|
-
console.log(`Terminal UI Features: ${uiTestResult ?
|
|
1643
|
-
console.log(`PDF Generation: ${pdfTestResult ?
|
|
1675
|
+
console.log("\n" + import_chalk2.default.bold.green("\u{1F389} Testing Complete!"));
|
|
1676
|
+
console.log(`Terminal UI Features: ${uiTestResult ? import_chalk2.default.green("\u2705 PASS") : import_chalk2.default.red("\u274C FAIL")}`);
|
|
1677
|
+
console.log(`PDF Generation: ${pdfTestResult ? import_chalk2.default.green("\u2705 PASS") : import_chalk2.default.yellow("\u26A0\uFE0F SKIP")}`);
|
|
1644
1678
|
if (uiTestResult) {
|
|
1645
|
-
console.log("\n" +
|
|
1679
|
+
console.log("\n" + import_chalk2.default.bold.cyan("Next Steps:"));
|
|
1646
1680
|
console.log("\u2022 Run with real AWS credentials: infra-cost --trend");
|
|
1647
1681
|
console.log("\u2022 Generate audit reports: infra-cost --audit --pdf-report");
|
|
1648
1682
|
console.log("\u2022 Create executive summaries: infra-cost --executive-summary");
|
|
1649
1683
|
}
|
|
1650
1684
|
} catch (error) {
|
|
1651
|
-
console.error(
|
|
1685
|
+
console.error(import_chalk2.default.red("\u274C Test failed:"), error instanceof Error ? error.message : error);
|
|
1652
1686
|
process.exit(1);
|
|
1653
1687
|
}
|
|
1654
1688
|
}
|
|
1655
|
-
if (
|
|
1689
|
+
if (import_meta.url === `file://${process.argv[1]}`) {
|
|
1656
1690
|
main();
|
|
1657
1691
|
}
|
|
1658
|
-
export
|
|
1692
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1693
|
+
0 && (module.exports = {
|
|
1659
1694
|
testEnhancedUI,
|
|
1660
1695
|
testPDFGeneration
|
|
1661
|
-
};
|
|
1662
|
-
//# sourceMappingURL=test-enhanced-ui.
|
|
1696
|
+
});
|
|
1697
|
+
//# sourceMappingURL=test-enhanced-ui.cjs.map
|