postboy-tui 1.3.8 → 1.4.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/cli.js +857 -326
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -67534,7 +67534,7 @@ var useFocusManager = () => {
|
|
|
67534
67534
|
};
|
|
67535
67535
|
var use_focus_manager_default = useFocusManager;
|
|
67536
67536
|
// src/ui/app/ui.tsx
|
|
67537
|
-
var
|
|
67537
|
+
var import_react35 = __toESM(require_react(), 1);
|
|
67538
67538
|
|
|
67539
67539
|
// src/utils/history.ts
|
|
67540
67540
|
import { promises as fs2 } from "fs";
|
|
@@ -67626,7 +67626,7 @@ var historyManager = new HistoryManager;
|
|
|
67626
67626
|
import http from "http";
|
|
67627
67627
|
import https from "https";
|
|
67628
67628
|
import { URL as URL2 } from "url";
|
|
67629
|
-
function sendRequest({ method, url, headers = {}, body }) {
|
|
67629
|
+
function sendRequest({ method, url, headers = {}, body, onProgress }) {
|
|
67630
67630
|
return new Promise((resolve, reject) => {
|
|
67631
67631
|
const urlObj = new URL2(url);
|
|
67632
67632
|
const isHttps = urlObj.protocol === "https:";
|
|
@@ -67649,12 +67649,26 @@ function sendRequest({ method, url, headers = {}, body }) {
|
|
|
67649
67649
|
const req = reqModule.request(options, (res) => {
|
|
67650
67650
|
timings.ttfb = performance.now();
|
|
67651
67651
|
let data = "";
|
|
67652
|
+
let bytesReceived = 0;
|
|
67653
|
+
const totalBytes = parseInt(res.headers["content-length"] || "0", 10);
|
|
67654
|
+
const downloadStartTime = performance.now();
|
|
67652
67655
|
res.on("data", (chunk) => {
|
|
67653
67656
|
data += chunk;
|
|
67657
|
+
bytesReceived += Buffer.byteLength(chunk);
|
|
67658
|
+
if (onProgress) {
|
|
67659
|
+
const elapsed = (performance.now() - downloadStartTime) / 1000;
|
|
67660
|
+
const speed = elapsed > 0 ? bytesReceived / elapsed : 0;
|
|
67661
|
+
onProgress({
|
|
67662
|
+
bytesReceived,
|
|
67663
|
+
totalBytes,
|
|
67664
|
+
speed,
|
|
67665
|
+
elapsed
|
|
67666
|
+
});
|
|
67667
|
+
}
|
|
67654
67668
|
});
|
|
67655
67669
|
res.on("end", () => {
|
|
67656
67670
|
timings.end = performance.now();
|
|
67657
|
-
const contentLength =
|
|
67671
|
+
const contentLength = totalBytes || Buffer.byteLength(data, "utf8");
|
|
67658
67672
|
const metrics = {
|
|
67659
67673
|
dnsLookup: timings.dnsLookup - timings.start,
|
|
67660
67674
|
tcpConnection: timings.tcpConnection - timings.dnsLookup,
|
|
@@ -69367,275 +69381,180 @@ var JsonSyntaxHighlight = import_react31.default.memo(({ jsonString, theme }) =>
|
|
|
69367
69381
|
|
|
69368
69382
|
// src/ui/app/components/responsepanel.tsx
|
|
69369
69383
|
var import_react32 = __toESM(require_react(), 1);
|
|
69370
|
-
|
|
69371
|
-
// src/ui/app/components/metricspanel.tsx
|
|
69372
69384
|
var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
|
|
69373
|
-
var
|
|
69374
|
-
const
|
|
69375
|
-
const
|
|
69376
|
-
|
|
69377
|
-
|
|
69378
|
-
|
|
69385
|
+
var StatusBadge = ({ status, statusText, theme }) => {
|
|
69386
|
+
const [glowFrame, setGlowFrame] = import_react32.useState(0);
|
|
69387
|
+
const statusNum = parseInt(status, 10);
|
|
69388
|
+
import_react32.useEffect(() => {
|
|
69389
|
+
const interval = setInterval(() => {
|
|
69390
|
+
setGlowFrame((prev) => (prev + 1) % 4);
|
|
69391
|
+
}, 300);
|
|
69392
|
+
return () => clearInterval(interval);
|
|
69393
|
+
}, []);
|
|
69394
|
+
const getStatusIcon = () => {
|
|
69395
|
+
if (statusNum >= 200 && statusNum < 300)
|
|
69396
|
+
return ["✓", "✔", "☑", "✓"][glowFrame];
|
|
69397
|
+
if (statusNum >= 300 && statusNum < 400)
|
|
69398
|
+
return ["↪", "→", "⇒", "↪"][glowFrame];
|
|
69399
|
+
if (statusNum >= 400 && statusNum < 500)
|
|
69400
|
+
return ["⚠", "⚡", "⚠", "⚡"][glowFrame];
|
|
69401
|
+
if (statusNum >= 500)
|
|
69402
|
+
return ["✗", "✘", "☒", "✗"][glowFrame];
|
|
69403
|
+
return "●";
|
|
69404
|
+
};
|
|
69405
|
+
const getBadgeStyle = () => {
|
|
69406
|
+
if (statusNum >= 200 && statusNum < 300)
|
|
69407
|
+
return { bg: theme.colors.success, icon: getStatusIcon(), label: "SUCCESS" };
|
|
69408
|
+
if (statusNum >= 300 && statusNum < 400)
|
|
69409
|
+
return { bg: theme.colors.accent, icon: getStatusIcon(), label: "REDIRECT" };
|
|
69410
|
+
if (statusNum >= 400 && statusNum < 500)
|
|
69411
|
+
return { bg: theme.colors.error, icon: getStatusIcon(), label: "CLIENT ERR" };
|
|
69412
|
+
if (statusNum >= 500)
|
|
69413
|
+
return { bg: theme.colors.error, icon: getStatusIcon(), label: "SERVER ERR" };
|
|
69414
|
+
return { bg: theme.colors.muted, icon: "●", label: "UNKNOWN" };
|
|
69415
|
+
};
|
|
69416
|
+
const style = getBadgeStyle();
|
|
69417
|
+
const glowChars = ["░", "▒", "▓", "▒"];
|
|
69418
|
+
if (!status || status === "Error") {
|
|
69419
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69420
|
+
children: [
|
|
69421
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69422
|
+
color: theme.colors.error,
|
|
69423
|
+
bold: true,
|
|
69424
|
+
children: "✗ "
|
|
69425
|
+
}, undefined, false, undefined, this),
|
|
69426
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69427
|
+
color: theme.colors.error,
|
|
69428
|
+
children: statusText || "Error"
|
|
69429
|
+
}, undefined, false, undefined, this)
|
|
69430
|
+
]
|
|
69431
|
+
}, undefined, true, undefined, this);
|
|
69432
|
+
}
|
|
69379
69433
|
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69380
|
-
marginY: 0,
|
|
69381
69434
|
children: [
|
|
69382
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(
|
|
69383
|
-
|
|
69384
|
-
|
|
69385
|
-
|
|
69386
|
-
children: label
|
|
69387
|
-
}, undefined, false, undefined, this)
|
|
69435
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69436
|
+
color: style.bg,
|
|
69437
|
+
dimColor: true,
|
|
69438
|
+
children: glowChars[glowFrame]
|
|
69388
69439
|
}, undefined, false, undefined, this),
|
|
69389
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(
|
|
69390
|
-
|
|
69391
|
-
|
|
69392
|
-
|
|
69393
|
-
|
|
69394
|
-
|
|
69440
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69441
|
+
backgroundColor: style.bg,
|
|
69442
|
+
color: theme.colors.white,
|
|
69443
|
+
bold: true,
|
|
69444
|
+
children: [
|
|
69445
|
+
" ",
|
|
69446
|
+
style.icon,
|
|
69447
|
+
" ",
|
|
69448
|
+
status,
|
|
69449
|
+
" "
|
|
69450
|
+
]
|
|
69451
|
+
}, undefined, true, undefined, this),
|
|
69452
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69453
|
+
color: style.bg,
|
|
69454
|
+
dimColor: true,
|
|
69455
|
+
children: glowChars[glowFrame]
|
|
69395
69456
|
}, undefined, false, undefined, this),
|
|
69396
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(
|
|
69397
|
-
|
|
69398
|
-
|
|
69399
|
-
|
|
69400
|
-
|
|
69401
|
-
|
|
69402
|
-
|
|
69403
|
-
|
|
69404
|
-
|
|
69405
|
-
|
|
69406
|
-
|
|
69457
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69458
|
+
color: theme.colors.muted,
|
|
69459
|
+
children: " │ "
|
|
69460
|
+
}, undefined, false, undefined, this),
|
|
69461
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69462
|
+
color: style.bg,
|
|
69463
|
+
bold: true,
|
|
69464
|
+
children: style.label
|
|
69465
|
+
}, undefined, false, undefined, this),
|
|
69466
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69467
|
+
color: theme.colors.muted,
|
|
69468
|
+
children: " │ "
|
|
69469
|
+
}, undefined, false, undefined, this),
|
|
69470
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69471
|
+
color: theme.colors.white,
|
|
69472
|
+
children: statusText
|
|
69407
69473
|
}, undefined, false, undefined, this)
|
|
69408
69474
|
]
|
|
69409
69475
|
}, undefined, true, undefined, this);
|
|
69410
69476
|
};
|
|
69411
|
-
var
|
|
69412
|
-
|
|
69413
|
-
|
|
69414
|
-
const
|
|
69415
|
-
|
|
69416
|
-
|
|
69417
|
-
|
|
69418
|
-
|
|
69419
|
-
|
|
69420
|
-
|
|
69421
|
-
|
|
69422
|
-
|
|
69423
|
-
|
|
69424
|
-
|
|
69425
|
-
|
|
69426
|
-
|
|
69427
|
-
|
|
69428
|
-
}
|
|
69429
|
-
}
|
|
69430
|
-
|
|
69477
|
+
var TypewriterText = ({ text, theme, speed = 2 }) => {
|
|
69478
|
+
const [displayedLength, setDisplayedLength] = import_react32.useState(0);
|
|
69479
|
+
const [cursorVisible, setCursorVisible] = import_react32.useState(true);
|
|
69480
|
+
const previousTextRef = import_react32.useRef("");
|
|
69481
|
+
import_react32.useEffect(() => {
|
|
69482
|
+
if (text !== previousTextRef.current) {
|
|
69483
|
+
setDisplayedLength(0);
|
|
69484
|
+
previousTextRef.current = text;
|
|
69485
|
+
}
|
|
69486
|
+
}, [text]);
|
|
69487
|
+
import_react32.useEffect(() => {
|
|
69488
|
+
if (displayedLength < text.length) {
|
|
69489
|
+
const charsToAdd = Math.min(speed, text.length - displayedLength);
|
|
69490
|
+
const timeout = setTimeout(() => {
|
|
69491
|
+
setDisplayedLength((prev) => Math.min(prev + charsToAdd, text.length));
|
|
69492
|
+
}, 5);
|
|
69493
|
+
return () => clearTimeout(timeout);
|
|
69494
|
+
}
|
|
69495
|
+
}, [displayedLength, text, speed]);
|
|
69496
|
+
import_react32.useEffect(() => {
|
|
69497
|
+
const interval = setInterval(() => {
|
|
69498
|
+
setCursorVisible((prev) => !prev);
|
|
69499
|
+
}, 400);
|
|
69500
|
+
return () => clearInterval(interval);
|
|
69501
|
+
}, []);
|
|
69502
|
+
const displayedText = text.slice(0, displayedLength);
|
|
69503
|
+
const isComplete = displayedLength >= text.length;
|
|
69504
|
+
const cursor = !isComplete && cursorVisible ? "█" : !isComplete ? " " : "";
|
|
69431
69505
|
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69432
69506
|
flexDirection: "column",
|
|
69433
|
-
paddingX: 1,
|
|
69434
69507
|
children: [
|
|
69435
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(
|
|
69436
|
-
|
|
69437
|
-
|
|
69438
|
-
children: [
|
|
69439
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69440
|
-
color: theme.colors.accent,
|
|
69441
|
-
bold: true,
|
|
69442
|
-
children: "⚡ Performance Breakdown"
|
|
69443
|
-
}, undefined, false, undefined, this),
|
|
69444
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69445
|
-
color: theme.colors.muted,
|
|
69446
|
-
children: "────────────────────────────────────────────────────────────"
|
|
69447
|
-
}, undefined, false, undefined, this)
|
|
69448
|
-
]
|
|
69449
|
-
}, undefined, true, undefined, this),
|
|
69450
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69451
|
-
flexDirection: "column",
|
|
69452
|
-
gap: 0,
|
|
69453
|
-
children: [
|
|
69454
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(MetricBar, {
|
|
69455
|
-
label: "\uD83D\uDD0D DNS Lookup",
|
|
69456
|
-
value: metrics.dnsLookup,
|
|
69457
|
-
maxValue: maxTime,
|
|
69458
|
-
color: theme.colors.cool,
|
|
69459
|
-
theme
|
|
69460
|
-
}, undefined, false, undefined, this),
|
|
69461
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(MetricBar, {
|
|
69462
|
-
label: "\uD83D\uDD0C TCP Connect",
|
|
69463
|
-
value: metrics.tcpConnection,
|
|
69464
|
-
maxValue: maxTime,
|
|
69465
|
-
color: theme.colors.success,
|
|
69466
|
-
theme
|
|
69467
|
-
}, undefined, false, undefined, this),
|
|
69468
|
-
metrics.tlsHandshake > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(MetricBar, {
|
|
69469
|
-
label: "\uD83D\uDD10 TLS Handshake",
|
|
69470
|
-
value: metrics.tlsHandshake,
|
|
69471
|
-
maxValue: maxTime,
|
|
69472
|
-
color: theme.colors.secondary,
|
|
69473
|
-
theme
|
|
69474
|
-
}, undefined, false, undefined, this),
|
|
69475
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(MetricBar, {
|
|
69476
|
-
label: "⏱️ TTFB",
|
|
69477
|
-
value: metrics.ttfb,
|
|
69478
|
-
maxValue: maxTime,
|
|
69479
|
-
color: theme.colors.accent,
|
|
69480
|
-
theme
|
|
69481
|
-
}, undefined, false, undefined, this),
|
|
69482
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(MetricBar, {
|
|
69483
|
-
label: "\uD83D\uDCE5 Download",
|
|
69484
|
-
value: metrics.contentDownload,
|
|
69485
|
-
maxValue: maxTime,
|
|
69486
|
-
color: theme.colors.primary,
|
|
69487
|
-
theme
|
|
69488
|
-
}, undefined, false, undefined, this)
|
|
69489
|
-
]
|
|
69490
|
-
}, undefined, true, undefined, this),
|
|
69491
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69492
|
-
marginTop: 1,
|
|
69493
|
-
flexDirection: "column",
|
|
69494
|
-
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69495
|
-
color: theme.colors.muted,
|
|
69496
|
-
children: "────────────────────────────────────────────────────────────"
|
|
69497
|
-
}, undefined, false, undefined, this)
|
|
69508
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(JsonSyntaxHighlight, {
|
|
69509
|
+
jsonString: displayedText,
|
|
69510
|
+
theme
|
|
69498
69511
|
}, undefined, false, undefined, this),
|
|
69499
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(
|
|
69500
|
-
|
|
69501
|
-
|
|
69502
|
-
|
|
69503
|
-
children: [
|
|
69504
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69505
|
-
children: [
|
|
69506
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69507
|
-
width: 18,
|
|
69508
|
-
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69509
|
-
color: theme.colors.accent,
|
|
69510
|
-
bold: true,
|
|
69511
|
-
children: "\uD83D\uDCCA Total Time"
|
|
69512
|
-
}, undefined, false, undefined, this)
|
|
69513
|
-
}, undefined, false, undefined, this),
|
|
69514
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69515
|
-
color: theme.colors.white,
|
|
69516
|
-
bold: true,
|
|
69517
|
-
children: [
|
|
69518
|
-
metrics.total.toFixed(2),
|
|
69519
|
-
" ms"
|
|
69520
|
-
]
|
|
69521
|
-
}, undefined, true, undefined, this)
|
|
69522
|
-
]
|
|
69523
|
-
}, undefined, true, undefined, this),
|
|
69524
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69525
|
-
children: [
|
|
69526
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69527
|
-
width: 18,
|
|
69528
|
-
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69529
|
-
color: theme.colors.accent,
|
|
69530
|
-
bold: true,
|
|
69531
|
-
children: "\uD83D\uDCE6 Size"
|
|
69532
|
-
}, undefined, false, undefined, this)
|
|
69533
|
-
}, undefined, false, undefined, this),
|
|
69534
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69535
|
-
color: theme.colors.white,
|
|
69536
|
-
bold: true,
|
|
69537
|
-
children: formatBytes(metrics.contentLength)
|
|
69538
|
-
}, undefined, false, undefined, this)
|
|
69539
|
-
]
|
|
69540
|
-
}, undefined, true, undefined, this),
|
|
69541
|
-
metrics.contentLength > 0 && metrics.contentDownload > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69542
|
-
children: [
|
|
69543
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69544
|
-
width: 18,
|
|
69545
|
-
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69546
|
-
color: theme.colors.accent,
|
|
69547
|
-
bold: true,
|
|
69548
|
-
children: "\uD83D\uDE80 Speed"
|
|
69549
|
-
}, undefined, false, undefined, this)
|
|
69550
|
-
}, undefined, false, undefined, this),
|
|
69551
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69552
|
-
color: theme.colors.success,
|
|
69553
|
-
bold: true,
|
|
69554
|
-
children: [
|
|
69555
|
-
formatBytes(metrics.contentLength / (metrics.contentDownload / 1000)),
|
|
69556
|
-
"/s"
|
|
69557
|
-
]
|
|
69558
|
-
}, undefined, true, undefined, this)
|
|
69559
|
-
]
|
|
69560
|
-
}, undefined, true, undefined, this)
|
|
69561
|
-
]
|
|
69562
|
-
}, undefined, true, undefined, this),
|
|
69563
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69564
|
-
marginTop: 1,
|
|
69565
|
-
flexDirection: "column",
|
|
69566
|
-
children: [
|
|
69567
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69568
|
-
color: theme.colors.muted,
|
|
69569
|
-
children: "────────────────────────────────────────────────────────────"
|
|
69570
|
-
}, undefined, false, undefined, this),
|
|
69571
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69572
|
-
marginTop: 1,
|
|
69573
|
-
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69574
|
-
color: theme.colors.muted,
|
|
69575
|
-
dimColor: true,
|
|
69576
|
-
children: "TTFB = Time To First Byte (DNS + TCP + TLS + Server Processing)"
|
|
69577
|
-
}, undefined, false, undefined, this)
|
|
69578
|
-
}, undefined, false, undefined, this)
|
|
69579
|
-
]
|
|
69580
|
-
}, undefined, true, undefined, this)
|
|
69512
|
+
!isComplete && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69513
|
+
color: theme.colors.accent,
|
|
69514
|
+
children: cursor
|
|
69515
|
+
}, undefined, false, undefined, this)
|
|
69581
69516
|
]
|
|
69582
69517
|
}, undefined, true, undefined, this);
|
|
69583
69518
|
};
|
|
69584
|
-
|
|
69585
|
-
// src/ui/app/components/responsepanel.tsx
|
|
69586
|
-
var jsx_dev_runtime11 = __toESM(require_jsx_dev_runtime(), 1);
|
|
69587
|
-
var ResponsePanel = import_react32.default.memo(({ response, theme, metrics = null }) => {
|
|
69519
|
+
var ResponsePanel = import_react32.default.memo(({ response, theme }) => {
|
|
69588
69520
|
const [activeTab, setActiveTab] = import_react32.useState("body");
|
|
69589
|
-
const tabs = [{ name: "body", label: "Body" }, { name: "headers", label: "Headers" }
|
|
69590
|
-
return /* @__PURE__ */
|
|
69521
|
+
const tabs = [{ name: "body", label: "Body" }, { name: "headers", label: "Headers" }];
|
|
69522
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69591
69523
|
flexDirection: "column",
|
|
69592
69524
|
flexGrow: 1,
|
|
69593
69525
|
children: [
|
|
69594
|
-
/* @__PURE__ */
|
|
69526
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69595
69527
|
marginBottom: 1,
|
|
69596
|
-
children:
|
|
69597
|
-
|
|
69598
|
-
|
|
69599
|
-
|
|
69600
|
-
|
|
69601
|
-
|
|
69602
|
-
|
|
69603
|
-
}, undefined, false, undefined, this),
|
|
69604
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69605
|
-
color: getStatusColor(response.status, theme),
|
|
69606
|
-
bold: true,
|
|
69607
|
-
children: [
|
|
69608
|
-
response.status,
|
|
69609
|
-
" ",
|
|
69610
|
-
response.statustext
|
|
69611
|
-
]
|
|
69612
|
-
}, undefined, true, undefined, this)
|
|
69613
|
-
]
|
|
69614
|
-
}, undefined, true, undefined, this),
|
|
69615
|
-
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Tabs, {
|
|
69528
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(StatusBadge, {
|
|
69529
|
+
status: response.status,
|
|
69530
|
+
statusText: response.statustext,
|
|
69531
|
+
theme
|
|
69532
|
+
}, undefined, false, undefined, this)
|
|
69533
|
+
}, undefined, false, undefined, this),
|
|
69534
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Tabs, {
|
|
69616
69535
|
tabs,
|
|
69617
69536
|
activeTab,
|
|
69618
69537
|
onChange: setActiveTab,
|
|
69619
69538
|
theme
|
|
69620
69539
|
}, undefined, false, undefined, this),
|
|
69621
|
-
/* @__PURE__ */
|
|
69540
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69622
69541
|
marginTop: 1,
|
|
69623
69542
|
flexGrow: 1,
|
|
69624
69543
|
children: [
|
|
69625
|
-
activeTab === "headers" && /* @__PURE__ */
|
|
69626
|
-
children: /* @__PURE__ */
|
|
69544
|
+
activeTab === "headers" && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(ScrollableBox, {
|
|
69545
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69627
69546
|
flexDirection: "column",
|
|
69628
|
-
children: Object.entries(JSON.parse(response.headers || "{}")).map(([key, value]) => /* @__PURE__ */
|
|
69547
|
+
children: Object.entries(JSON.parse(response.headers || "{}")).map(([key, value]) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69629
69548
|
children: [
|
|
69630
|
-
/* @__PURE__ */
|
|
69549
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69631
69550
|
color: theme.colors.accent,
|
|
69632
69551
|
children: key
|
|
69633
69552
|
}, undefined, false, undefined, this),
|
|
69634
|
-
/* @__PURE__ */
|
|
69553
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69635
69554
|
color: theme.colors.muted,
|
|
69636
69555
|
children: ": "
|
|
69637
69556
|
}, undefined, false, undefined, this),
|
|
69638
|
-
/* @__PURE__ */
|
|
69557
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69639
69558
|
color: theme.colors.success,
|
|
69640
69559
|
children: String(value)
|
|
69641
69560
|
}, undefined, false, undefined, this)
|
|
@@ -69643,21 +69562,16 @@ var ResponsePanel = import_react32.default.memo(({ response, theme, metrics = nu
|
|
|
69643
69562
|
}, key, true, undefined, this))
|
|
69644
69563
|
}, undefined, false, undefined, this)
|
|
69645
69564
|
}, undefined, false, undefined, this),
|
|
69646
|
-
activeTab === "body" && /* @__PURE__ */
|
|
69647
|
-
children: /* @__PURE__ */
|
|
69565
|
+
activeTab === "body" && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(ScrollableBox, {
|
|
69566
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69648
69567
|
flexDirection: "column",
|
|
69649
69568
|
flexGrow: 1,
|
|
69650
|
-
children: /* @__PURE__ */
|
|
69651
|
-
|
|
69652
|
-
theme
|
|
69569
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(TypewriterText, {
|
|
69570
|
+
text: response.body,
|
|
69571
|
+
theme,
|
|
69572
|
+
speed: 50
|
|
69653
69573
|
}, undefined, false, undefined, this)
|
|
69654
69574
|
}, undefined, false, undefined, this)
|
|
69655
|
-
}, undefined, false, undefined, this),
|
|
69656
|
-
activeTab === "metrics" && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(ScrollableBox, {
|
|
69657
|
-
children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(MetricsPanel, {
|
|
69658
|
-
metrics,
|
|
69659
|
-
theme
|
|
69660
|
-
}, undefined, false, undefined, this)
|
|
69661
69575
|
}, undefined, false, undefined, this)
|
|
69662
69576
|
]
|
|
69663
69577
|
}, undefined, true, undefined, this)
|
|
@@ -69754,7 +69668,7 @@ var saveToFile = async (content, filePath) => {
|
|
|
69754
69668
|
};
|
|
69755
69669
|
|
|
69756
69670
|
// src/ui/app/components/exportdialog.tsx
|
|
69757
|
-
var
|
|
69671
|
+
var jsx_dev_runtime11 = __toESM(require_jsx_dev_runtime(), 1);
|
|
69758
69672
|
var EXPORT_DIR = `${process.env.HOME}/.postboy/exports`;
|
|
69759
69673
|
var ExportDialog = ({ request, onClose, theme }) => {
|
|
69760
69674
|
const [format, setFormat] = import_react33.useState("curl");
|
|
@@ -69834,58 +69748,58 @@ ${finalPath}` : "Failed to save file");
|
|
|
69834
69748
|
}
|
|
69835
69749
|
});
|
|
69836
69750
|
const preview = getExportContent();
|
|
69837
|
-
return /* @__PURE__ */
|
|
69751
|
+
return /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69838
69752
|
flexDirection: "column",
|
|
69839
69753
|
borderStyle: "double",
|
|
69840
69754
|
borderColor: theme.accent,
|
|
69841
69755
|
padding: 1,
|
|
69842
69756
|
children: [
|
|
69843
|
-
/* @__PURE__ */
|
|
69757
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69844
69758
|
marginBottom: 1,
|
|
69845
69759
|
children: [
|
|
69846
|
-
/* @__PURE__ */
|
|
69760
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69847
69761
|
color: theme.accent,
|
|
69848
69762
|
bold: true,
|
|
69849
69763
|
children: "Export Request"
|
|
69850
69764
|
}, undefined, false, undefined, this),
|
|
69851
|
-
/* @__PURE__ */
|
|
69765
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69852
69766
|
color: theme.muted,
|
|
69853
69767
|
children: " (Tab: switch, ←→: select, Enter: confirm, Esc: cancel)"
|
|
69854
69768
|
}, undefined, false, undefined, this)
|
|
69855
69769
|
]
|
|
69856
69770
|
}, undefined, true, undefined, this),
|
|
69857
|
-
message ? /* @__PURE__ */
|
|
69771
|
+
message ? /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69858
69772
|
padding: 1,
|
|
69859
69773
|
flexDirection: "column",
|
|
69860
69774
|
borderStyle: "round",
|
|
69861
69775
|
borderColor: theme.success,
|
|
69862
69776
|
children: message.split(`
|
|
69863
|
-
`).map((line, i) => /* @__PURE__ */
|
|
69777
|
+
`).map((line, i) => /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69864
69778
|
color: theme.success,
|
|
69865
69779
|
bold: true,
|
|
69866
69780
|
children: line
|
|
69867
69781
|
}, i, false, undefined, this))
|
|
69868
|
-
}, undefined, false, undefined, this) : showSavePrompt ? /* @__PURE__ */
|
|
69782
|
+
}, undefined, false, undefined, this) : showSavePrompt ? /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69869
69783
|
flexDirection: "column",
|
|
69870
69784
|
gap: 1,
|
|
69871
69785
|
children: [
|
|
69872
|
-
/* @__PURE__ */
|
|
69786
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69873
69787
|
children: [
|
|
69874
|
-
/* @__PURE__ */
|
|
69788
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69875
69789
|
color: theme.primary,
|
|
69876
69790
|
children: "File path: "
|
|
69877
69791
|
}, undefined, false, undefined, this),
|
|
69878
|
-
/* @__PURE__ */
|
|
69792
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69879
69793
|
borderStyle: "round",
|
|
69880
69794
|
borderColor: theme.accent,
|
|
69881
69795
|
paddingX: 1,
|
|
69882
69796
|
flexGrow: 1,
|
|
69883
69797
|
children: [
|
|
69884
|
-
/* @__PURE__ */
|
|
69798
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69885
69799
|
color: theme.white,
|
|
69886
69800
|
children: filePath
|
|
69887
69801
|
}, undefined, false, undefined, this),
|
|
69888
|
-
/* @__PURE__ */
|
|
69802
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69889
69803
|
color: theme.accent,
|
|
69890
69804
|
children: "▌"
|
|
69891
69805
|
}, undefined, false, undefined, this)
|
|
@@ -69893,7 +69807,7 @@ ${finalPath}` : "Failed to save file");
|
|
|
69893
69807
|
}, undefined, true, undefined, this)
|
|
69894
69808
|
]
|
|
69895
69809
|
}, undefined, true, undefined, this),
|
|
69896
|
-
/* @__PURE__ */
|
|
69810
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69897
69811
|
color: theme.muted,
|
|
69898
69812
|
children: [
|
|
69899
69813
|
"Extension .",
|
|
@@ -69902,32 +69816,32 @@ ${finalPath}` : "Failed to save file");
|
|
|
69902
69816
|
]
|
|
69903
69817
|
}, undefined, true, undefined, this)
|
|
69904
69818
|
]
|
|
69905
|
-
}, undefined, true, undefined, this) : /* @__PURE__ */
|
|
69819
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69906
69820
|
flexDirection: "column",
|
|
69907
69821
|
gap: 1,
|
|
69908
69822
|
children: [
|
|
69909
|
-
/* @__PURE__ */
|
|
69823
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69910
69824
|
gap: 2,
|
|
69911
69825
|
children: [
|
|
69912
|
-
/* @__PURE__ */
|
|
69826
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69913
69827
|
color: theme.primary,
|
|
69914
69828
|
children: "Format: "
|
|
69915
69829
|
}, undefined, false, undefined, this),
|
|
69916
|
-
/* @__PURE__ */
|
|
69830
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69917
69831
|
borderStyle: "round",
|
|
69918
69832
|
borderColor: activeField === "format" && format === "curl" ? theme.accent : theme.muted,
|
|
69919
69833
|
paddingX: 1,
|
|
69920
|
-
children: /* @__PURE__ */
|
|
69834
|
+
children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69921
69835
|
color: format === "curl" ? theme.accent : theme.muted,
|
|
69922
69836
|
bold: format === "curl",
|
|
69923
69837
|
children: "cURL"
|
|
69924
69838
|
}, undefined, false, undefined, this)
|
|
69925
69839
|
}, undefined, false, undefined, this),
|
|
69926
|
-
/* @__PURE__ */
|
|
69840
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69927
69841
|
borderStyle: "round",
|
|
69928
69842
|
borderColor: activeField === "format" && format === "fetch" ? theme.accent : theme.muted,
|
|
69929
69843
|
paddingX: 1,
|
|
69930
|
-
children: /* @__PURE__ */
|
|
69844
|
+
children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69931
69845
|
color: format === "fetch" ? theme.accent : theme.muted,
|
|
69932
69846
|
bold: format === "fetch",
|
|
69933
69847
|
children: "Fetch"
|
|
@@ -69935,28 +69849,28 @@ ${finalPath}` : "Failed to save file");
|
|
|
69935
69849
|
}, undefined, false, undefined, this)
|
|
69936
69850
|
]
|
|
69937
69851
|
}, undefined, true, undefined, this),
|
|
69938
|
-
/* @__PURE__ */
|
|
69852
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69939
69853
|
gap: 2,
|
|
69940
69854
|
children: [
|
|
69941
|
-
/* @__PURE__ */
|
|
69855
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69942
69856
|
color: theme.primary,
|
|
69943
69857
|
children: "Action: "
|
|
69944
69858
|
}, undefined, false, undefined, this),
|
|
69945
|
-
/* @__PURE__ */
|
|
69859
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69946
69860
|
borderStyle: "round",
|
|
69947
69861
|
borderColor: activeField === "action" && action === "copy" ? theme.accent : theme.muted,
|
|
69948
69862
|
paddingX: 1,
|
|
69949
|
-
children: /* @__PURE__ */
|
|
69863
|
+
children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69950
69864
|
color: action === "copy" ? theme.accent : theme.muted,
|
|
69951
69865
|
bold: action === "copy",
|
|
69952
69866
|
children: "Copy to Clipboard"
|
|
69953
69867
|
}, undefined, false, undefined, this)
|
|
69954
69868
|
}, undefined, false, undefined, this),
|
|
69955
|
-
/* @__PURE__ */
|
|
69869
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69956
69870
|
borderStyle: "round",
|
|
69957
69871
|
borderColor: activeField === "action" && action === "save" ? theme.accent : theme.muted,
|
|
69958
69872
|
paddingX: 1,
|
|
69959
|
-
children: /* @__PURE__ */
|
|
69873
|
+
children: /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69960
69874
|
color: action === "save" ? theme.accent : theme.muted,
|
|
69961
69875
|
bold: action === "save",
|
|
69962
69876
|
children: "Save to File"
|
|
@@ -69964,21 +69878,21 @@ ${finalPath}` : "Failed to save file");
|
|
|
69964
69878
|
}, undefined, false, undefined, this)
|
|
69965
69879
|
]
|
|
69966
69880
|
}, undefined, true, undefined, this),
|
|
69967
|
-
/* @__PURE__ */
|
|
69881
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69968
69882
|
flexDirection: "column",
|
|
69969
69883
|
marginTop: 1,
|
|
69970
69884
|
children: [
|
|
69971
|
-
/* @__PURE__ */
|
|
69885
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69972
69886
|
color: theme.primary,
|
|
69973
69887
|
children: "Preview:"
|
|
69974
69888
|
}, undefined, false, undefined, this),
|
|
69975
|
-
/* @__PURE__ */
|
|
69889
|
+
/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Box_default, {
|
|
69976
69890
|
borderStyle: "round",
|
|
69977
69891
|
borderColor: theme.muted,
|
|
69978
69892
|
padding: 1,
|
|
69979
69893
|
flexDirection: "column",
|
|
69980
69894
|
children: preview.split(`
|
|
69981
|
-
`).map((line, i) => /* @__PURE__ */
|
|
69895
|
+
`).map((line, i) => /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
|
|
69982
69896
|
color: theme.white,
|
|
69983
69897
|
children: line
|
|
69984
69898
|
}, i, false, undefined, this))
|
|
@@ -70093,32 +70007,617 @@ class ThemeManager {
|
|
|
70093
70007
|
}
|
|
70094
70008
|
var themeManager = new ThemeManager;
|
|
70095
70009
|
|
|
70096
|
-
// src/ui/app/
|
|
70097
|
-
var
|
|
70098
|
-
var
|
|
70099
|
-
|
|
70100
|
-
|
|
70101
|
-
|
|
70102
|
-
|
|
70103
|
-
|
|
70104
|
-
|
|
70105
|
-
|
|
70106
|
-
|
|
70107
|
-
|
|
70108
|
-
|
|
70109
|
-
|
|
70110
|
-
|
|
70111
|
-
|
|
70112
|
-
|
|
70113
|
-
|
|
70114
|
-
|
|
70115
|
-
|
|
70116
|
-
|
|
70117
|
-
|
|
70118
|
-
|
|
70119
|
-
|
|
70120
|
-
|
|
70121
|
-
|
|
70010
|
+
// src/ui/app/components/metricspanel.tsx
|
|
70011
|
+
var import_react34 = __toESM(require_react(), 1);
|
|
70012
|
+
var jsx_dev_runtime12 = __toESM(require_jsx_dev_runtime(), 1);
|
|
70013
|
+
var BAR_CHARS = ["▱", "▰"];
|
|
70014
|
+
var GLOW_FRAMES = ["◐", "◓", "◑", "◒"];
|
|
70015
|
+
var SPARK_CHARS = ["⚡", "✦", "✧", "⚡", "★", "☆"];
|
|
70016
|
+
var MetricBar = ({ label, value, maxValue, color, theme, delay }) => {
|
|
70017
|
+
const barWidth = 30;
|
|
70018
|
+
const safeValue = Math.max(0, value);
|
|
70019
|
+
const targetFilled = Math.max(0, Math.min(barWidth, maxValue > 0 ? Math.round(safeValue / maxValue * barWidth) : 0));
|
|
70020
|
+
const [animatedFilled, setAnimatedFilled] = import_react34.useState(0);
|
|
70021
|
+
const [glowFrame, setGlowFrame] = import_react34.useState(0);
|
|
70022
|
+
const [sparkle, setSparkle] = import_react34.useState(false);
|
|
70023
|
+
import_react34.useEffect(() => {
|
|
70024
|
+
const timeout = setTimeout(() => {
|
|
70025
|
+
if (animatedFilled < targetFilled) {
|
|
70026
|
+
const interval = setInterval(() => {
|
|
70027
|
+
setAnimatedFilled((prev) => {
|
|
70028
|
+
if (prev >= targetFilled) {
|
|
70029
|
+
clearInterval(interval);
|
|
70030
|
+
setSparkle(true);
|
|
70031
|
+
setTimeout(() => setSparkle(false), 300);
|
|
70032
|
+
return targetFilled;
|
|
70033
|
+
}
|
|
70034
|
+
return prev + 1;
|
|
70035
|
+
});
|
|
70036
|
+
}, 20);
|
|
70037
|
+
return () => clearInterval(interval);
|
|
70038
|
+
}
|
|
70039
|
+
}, delay);
|
|
70040
|
+
return () => clearTimeout(timeout);
|
|
70041
|
+
}, [targetFilled, delay]);
|
|
70042
|
+
import_react34.useEffect(() => {
|
|
70043
|
+
const interval = setInterval(() => {
|
|
70044
|
+
setGlowFrame((prev) => (prev + 1) % GLOW_FRAMES.length);
|
|
70045
|
+
}, 150);
|
|
70046
|
+
return () => clearInterval(interval);
|
|
70047
|
+
}, []);
|
|
70048
|
+
const filledBar = BAR_CHARS[1].repeat(animatedFilled);
|
|
70049
|
+
const emptyBar = BAR_CHARS[0].repeat(barWidth - animatedFilled);
|
|
70050
|
+
const indicator = animatedFilled > 0 && animatedFilled < targetFilled ? GLOW_FRAMES[glowFrame] : sparkle ? SPARK_CHARS[Math.floor(Math.random() * SPARK_CHARS.length)] : "";
|
|
70051
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70052
|
+
marginY: 0,
|
|
70053
|
+
children: [
|
|
70054
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70055
|
+
width: 16,
|
|
70056
|
+
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70057
|
+
color,
|
|
70058
|
+
bold: true,
|
|
70059
|
+
children: label
|
|
70060
|
+
}, undefined, false, undefined, this)
|
|
70061
|
+
}, undefined, false, undefined, this),
|
|
70062
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70063
|
+
color: theme.colors.muted,
|
|
70064
|
+
children: "│"
|
|
70065
|
+
}, undefined, false, undefined, this),
|
|
70066
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70067
|
+
width: barWidth + 3,
|
|
70068
|
+
children: [
|
|
70069
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70070
|
+
color,
|
|
70071
|
+
children: filledBar
|
|
70072
|
+
}, undefined, false, undefined, this),
|
|
70073
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70074
|
+
color,
|
|
70075
|
+
bold: true,
|
|
70076
|
+
children: indicator
|
|
70077
|
+
}, undefined, false, undefined, this),
|
|
70078
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70079
|
+
color: theme.colors.muted,
|
|
70080
|
+
dimColor: true,
|
|
70081
|
+
children: emptyBar
|
|
70082
|
+
}, undefined, false, undefined, this)
|
|
70083
|
+
]
|
|
70084
|
+
}, undefined, true, undefined, this),
|
|
70085
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70086
|
+
color: theme.colors.muted,
|
|
70087
|
+
children: "│"
|
|
70088
|
+
}, undefined, false, undefined, this),
|
|
70089
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70090
|
+
width: 10,
|
|
70091
|
+
justifyContent: "flex-end",
|
|
70092
|
+
children: [
|
|
70093
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70094
|
+
color: theme.colors.white,
|
|
70095
|
+
bold: true,
|
|
70096
|
+
children: safeValue.toFixed(1)
|
|
70097
|
+
}, undefined, false, undefined, this),
|
|
70098
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70099
|
+
color: theme.colors.muted,
|
|
70100
|
+
dimColor: true,
|
|
70101
|
+
children: "ms"
|
|
70102
|
+
}, undefined, false, undefined, this)
|
|
70103
|
+
]
|
|
70104
|
+
}, undefined, true, undefined, this)
|
|
70105
|
+
]
|
|
70106
|
+
}, undefined, true, undefined, this);
|
|
70107
|
+
};
|
|
70108
|
+
var formatBytes = (bytes) => {
|
|
70109
|
+
if (bytes === 0)
|
|
70110
|
+
return "0 B";
|
|
70111
|
+
const k = 1024;
|
|
70112
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
70113
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
70114
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
70115
|
+
};
|
|
70116
|
+
var AnimatedValue = ({ value, suffix, color }) => {
|
|
70117
|
+
const [displayValue, setDisplayValue] = import_react34.useState(0);
|
|
70118
|
+
import_react34.useEffect(() => {
|
|
70119
|
+
const duration = 500;
|
|
70120
|
+
const steps = 20;
|
|
70121
|
+
const increment = value / steps;
|
|
70122
|
+
let current = 0;
|
|
70123
|
+
const interval = setInterval(() => {
|
|
70124
|
+
current += increment;
|
|
70125
|
+
if (current >= value) {
|
|
70126
|
+
setDisplayValue(value);
|
|
70127
|
+
clearInterval(interval);
|
|
70128
|
+
} else {
|
|
70129
|
+
setDisplayValue(current);
|
|
70130
|
+
}
|
|
70131
|
+
}, duration / steps);
|
|
70132
|
+
return () => clearInterval(interval);
|
|
70133
|
+
}, [value]);
|
|
70134
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70135
|
+
color,
|
|
70136
|
+
bold: true,
|
|
70137
|
+
children: [
|
|
70138
|
+
displayValue.toFixed(2),
|
|
70139
|
+
" ",
|
|
70140
|
+
suffix
|
|
70141
|
+
]
|
|
70142
|
+
}, undefined, true, undefined, this);
|
|
70143
|
+
};
|
|
70144
|
+
var PulsingDot = ({ color }) => {
|
|
70145
|
+
const [frame, setFrame] = import_react34.useState(0);
|
|
70146
|
+
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
70147
|
+
import_react34.useEffect(() => {
|
|
70148
|
+
const interval = setInterval(() => {
|
|
70149
|
+
setFrame((prev) => (prev + 1) % frames.length);
|
|
70150
|
+
}, 80);
|
|
70151
|
+
return () => clearInterval(interval);
|
|
70152
|
+
}, []);
|
|
70153
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70154
|
+
color,
|
|
70155
|
+
children: frames[frame]
|
|
70156
|
+
}, undefined, false, undefined, this);
|
|
70157
|
+
};
|
|
70158
|
+
var TimelineWaterfall = ({ metrics, theme }) => {
|
|
70159
|
+
const [animationProgress, setAnimationProgress] = import_react34.useState(0);
|
|
70160
|
+
const [pulseFrame, setPulseFrame] = import_react34.useState(0);
|
|
70161
|
+
const totalWidth = 50;
|
|
70162
|
+
const segments = [
|
|
70163
|
+
{ label: "DNS", value: Math.max(0, metrics.dnsLookup), color: theme.colors.cool, icon: "⚡" },
|
|
70164
|
+
{ label: "TCP", value: Math.max(0, metrics.tcpConnection), color: theme.colors.success, icon: "\uD83D\uDD0C" },
|
|
70165
|
+
...metrics.tlsHandshake > 0 ? [{ label: "TLS", value: Math.max(0, metrics.tlsHandshake), color: theme.colors.secondary, icon: "\uD83D\uDD10" }] : [],
|
|
70166
|
+
{ label: "TTFB", value: Math.max(0, metrics.ttfb), color: theme.colors.accent, icon: "⏱️" },
|
|
70167
|
+
{ label: "DL", value: Math.max(0, metrics.contentDownload), color: theme.colors.primary, icon: "\uD83D\uDCE5" }
|
|
70168
|
+
];
|
|
70169
|
+
const totalTime = segments.reduce((sum, s) => sum + s.value, 0);
|
|
70170
|
+
import_react34.useEffect(() => {
|
|
70171
|
+
setAnimationProgress(0);
|
|
70172
|
+
const interval = setInterval(() => {
|
|
70173
|
+
setAnimationProgress((prev) => {
|
|
70174
|
+
if (prev >= 100) {
|
|
70175
|
+
clearInterval(interval);
|
|
70176
|
+
return 100;
|
|
70177
|
+
}
|
|
70178
|
+
return prev + 2;
|
|
70179
|
+
});
|
|
70180
|
+
}, 15);
|
|
70181
|
+
return () => clearInterval(interval);
|
|
70182
|
+
}, [metrics]);
|
|
70183
|
+
import_react34.useEffect(() => {
|
|
70184
|
+
const interval = setInterval(() => {
|
|
70185
|
+
setPulseFrame((prev) => (prev + 1) % 4);
|
|
70186
|
+
}, 200);
|
|
70187
|
+
return () => clearInterval(interval);
|
|
70188
|
+
}, []);
|
|
70189
|
+
const pulseChars = ["▁", "▂", "▃", "▄"];
|
|
70190
|
+
const endCaps = ["◀", "▶"];
|
|
70191
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70192
|
+
flexDirection: "column",
|
|
70193
|
+
marginY: 1,
|
|
70194
|
+
children: [
|
|
70195
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70196
|
+
marginBottom: 1,
|
|
70197
|
+
children: [
|
|
70198
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70199
|
+
color: theme.colors.accent,
|
|
70200
|
+
bold: true,
|
|
70201
|
+
children: "⏳ Request Timeline"
|
|
70202
|
+
}, undefined, false, undefined, this),
|
|
70203
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70204
|
+
color: theme.colors.muted,
|
|
70205
|
+
children: [
|
|
70206
|
+
" (",
|
|
70207
|
+
totalTime.toFixed(0),
|
|
70208
|
+
"ms total)"
|
|
70209
|
+
]
|
|
70210
|
+
}, undefined, true, undefined, this)
|
|
70211
|
+
]
|
|
70212
|
+
}, undefined, true, undefined, this),
|
|
70213
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70214
|
+
children: [
|
|
70215
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70216
|
+
color: theme.colors.muted,
|
|
70217
|
+
children: endCaps[0]
|
|
70218
|
+
}, undefined, false, undefined, this),
|
|
70219
|
+
segments.map((segment, idx) => {
|
|
70220
|
+
const segmentWidth = Math.max(1, Math.round(segment.value / totalTime * totalWidth));
|
|
70221
|
+
const animatedWidth = Math.round(animationProgress / 100 * segmentWidth);
|
|
70222
|
+
const filledPart = "█".repeat(Math.max(0, animatedWidth));
|
|
70223
|
+
const emptyPart = "░".repeat(Math.max(0, segmentWidth - animatedWidth));
|
|
70224
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70225
|
+
children: [
|
|
70226
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70227
|
+
color: segment.color,
|
|
70228
|
+
children: filledPart
|
|
70229
|
+
}, undefined, false, undefined, this),
|
|
70230
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70231
|
+
color: segment.color,
|
|
70232
|
+
dimColor: true,
|
|
70233
|
+
children: emptyPart
|
|
70234
|
+
}, undefined, false, undefined, this)
|
|
70235
|
+
]
|
|
70236
|
+
}, idx, true, undefined, this);
|
|
70237
|
+
}),
|
|
70238
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70239
|
+
color: theme.colors.muted,
|
|
70240
|
+
children: endCaps[1]
|
|
70241
|
+
}, undefined, false, undefined, this),
|
|
70242
|
+
animationProgress < 100 && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70243
|
+
color: theme.colors.accent,
|
|
70244
|
+
children: [
|
|
70245
|
+
" ",
|
|
70246
|
+
pulseChars[pulseFrame]
|
|
70247
|
+
]
|
|
70248
|
+
}, undefined, true, undefined, this),
|
|
70249
|
+
animationProgress >= 100 && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70250
|
+
color: theme.colors.success,
|
|
70251
|
+
children: " ✓"
|
|
70252
|
+
}, undefined, false, undefined, this)
|
|
70253
|
+
]
|
|
70254
|
+
}, undefined, true, undefined, this),
|
|
70255
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70256
|
+
marginTop: 1,
|
|
70257
|
+
flexWrap: "wrap",
|
|
70258
|
+
children: segments.map((segment, idx) => /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70259
|
+
marginRight: 2,
|
|
70260
|
+
children: [
|
|
70261
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70262
|
+
color: segment.color,
|
|
70263
|
+
children: "■"
|
|
70264
|
+
}, undefined, false, undefined, this),
|
|
70265
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70266
|
+
color: theme.colors.muted,
|
|
70267
|
+
children: [
|
|
70268
|
+
" ",
|
|
70269
|
+
segment.label,
|
|
70270
|
+
" "
|
|
70271
|
+
]
|
|
70272
|
+
}, undefined, true, undefined, this),
|
|
70273
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70274
|
+
color: theme.colors.white,
|
|
70275
|
+
bold: true,
|
|
70276
|
+
children: segment.value.toFixed(0)
|
|
70277
|
+
}, undefined, false, undefined, this),
|
|
70278
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70279
|
+
color: theme.colors.muted,
|
|
70280
|
+
dimColor: true,
|
|
70281
|
+
children: "ms"
|
|
70282
|
+
}, undefined, false, undefined, this)
|
|
70283
|
+
]
|
|
70284
|
+
}, idx, true, undefined, this))
|
|
70285
|
+
}, undefined, false, undefined, this)
|
|
70286
|
+
]
|
|
70287
|
+
}, undefined, true, undefined, this);
|
|
70288
|
+
};
|
|
70289
|
+
var MetricsPanel = ({ metrics, theme }) => {
|
|
70290
|
+
const [showContent, setShowContent] = import_react34.useState(false);
|
|
70291
|
+
import_react34.useEffect(() => {
|
|
70292
|
+
if (metrics) {
|
|
70293
|
+
setShowContent(false);
|
|
70294
|
+
const timeout = setTimeout(() => setShowContent(true), 100);
|
|
70295
|
+
return () => clearTimeout(timeout);
|
|
70296
|
+
}
|
|
70297
|
+
}, [metrics]);
|
|
70298
|
+
if (!metrics) {
|
|
70299
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70300
|
+
flexDirection: "column",
|
|
70301
|
+
padding: 1,
|
|
70302
|
+
alignItems: "center",
|
|
70303
|
+
children: [
|
|
70304
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70305
|
+
marginBottom: 1,
|
|
70306
|
+
children: [
|
|
70307
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(PulsingDot, {
|
|
70308
|
+
color: theme.colors.muted
|
|
70309
|
+
}, undefined, false, undefined, this),
|
|
70310
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70311
|
+
color: theme.colors.muted,
|
|
70312
|
+
children: " Waiting for request..."
|
|
70313
|
+
}, undefined, false, undefined, this)
|
|
70314
|
+
]
|
|
70315
|
+
}, undefined, true, undefined, this),
|
|
70316
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70317
|
+
color: theme.colors.muted,
|
|
70318
|
+
dimColor: true,
|
|
70319
|
+
children: "Send a request to see metrics"
|
|
70320
|
+
}, undefined, false, undefined, this)
|
|
70321
|
+
]
|
|
70322
|
+
}, undefined, true, undefined, this);
|
|
70323
|
+
}
|
|
70324
|
+
const maxTime = Math.max(Math.max(0, metrics.dnsLookup), Math.max(0, metrics.tcpConnection), Math.max(0, metrics.tlsHandshake), Math.max(0, metrics.ttfb), Math.max(0, metrics.contentDownload), 1);
|
|
70325
|
+
if (!showContent) {
|
|
70326
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70327
|
+
flexDirection: "column",
|
|
70328
|
+
padding: 1,
|
|
70329
|
+
alignItems: "center",
|
|
70330
|
+
children: [
|
|
70331
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(PulsingDot, {
|
|
70332
|
+
color: theme.colors.accent
|
|
70333
|
+
}, undefined, false, undefined, this),
|
|
70334
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70335
|
+
color: theme.colors.accent,
|
|
70336
|
+
children: " Analyzing..."
|
|
70337
|
+
}, undefined, false, undefined, this)
|
|
70338
|
+
]
|
|
70339
|
+
}, undefined, true, undefined, this);
|
|
70340
|
+
}
|
|
70341
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70342
|
+
flexDirection: "column",
|
|
70343
|
+
paddingX: 1,
|
|
70344
|
+
children: [
|
|
70345
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(TimelineWaterfall, {
|
|
70346
|
+
metrics,
|
|
70347
|
+
theme
|
|
70348
|
+
}, undefined, false, undefined, this),
|
|
70349
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70350
|
+
marginTop: 1,
|
|
70351
|
+
flexDirection: "column",
|
|
70352
|
+
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70353
|
+
color: theme.colors.muted,
|
|
70354
|
+
children: "┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈"
|
|
70355
|
+
}, undefined, false, undefined, this)
|
|
70356
|
+
}, undefined, false, undefined, this),
|
|
70357
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70358
|
+
flexDirection: "column",
|
|
70359
|
+
gap: 0,
|
|
70360
|
+
children: [
|
|
70361
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(MetricBar, {
|
|
70362
|
+
label: "⚡ DNS",
|
|
70363
|
+
value: metrics.dnsLookup,
|
|
70364
|
+
maxValue: maxTime,
|
|
70365
|
+
color: theme.colors.cool,
|
|
70366
|
+
theme,
|
|
70367
|
+
delay: 0
|
|
70368
|
+
}, undefined, false, undefined, this),
|
|
70369
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(MetricBar, {
|
|
70370
|
+
label: "\uD83D\uDD0C TCP",
|
|
70371
|
+
value: metrics.tcpConnection,
|
|
70372
|
+
maxValue: maxTime,
|
|
70373
|
+
color: theme.colors.success,
|
|
70374
|
+
theme,
|
|
70375
|
+
delay: 100
|
|
70376
|
+
}, undefined, false, undefined, this),
|
|
70377
|
+
metrics.tlsHandshake > 0 && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(MetricBar, {
|
|
70378
|
+
label: "\uD83D\uDD10 TLS",
|
|
70379
|
+
value: metrics.tlsHandshake,
|
|
70380
|
+
maxValue: maxTime,
|
|
70381
|
+
color: theme.colors.secondary,
|
|
70382
|
+
theme,
|
|
70383
|
+
delay: 200
|
|
70384
|
+
}, undefined, false, undefined, this),
|
|
70385
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(MetricBar, {
|
|
70386
|
+
label: "⏱️ TTFB",
|
|
70387
|
+
value: metrics.ttfb,
|
|
70388
|
+
maxValue: maxTime,
|
|
70389
|
+
color: theme.colors.accent,
|
|
70390
|
+
theme,
|
|
70391
|
+
delay: 300
|
|
70392
|
+
}, undefined, false, undefined, this),
|
|
70393
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(MetricBar, {
|
|
70394
|
+
label: "\uD83D\uDCE5 Download",
|
|
70395
|
+
value: metrics.contentDownload,
|
|
70396
|
+
maxValue: maxTime,
|
|
70397
|
+
color: theme.colors.primary,
|
|
70398
|
+
theme,
|
|
70399
|
+
delay: 400
|
|
70400
|
+
}, undefined, false, undefined, this)
|
|
70401
|
+
]
|
|
70402
|
+
}, undefined, true, undefined, this),
|
|
70403
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70404
|
+
marginTop: 1,
|
|
70405
|
+
flexDirection: "column",
|
|
70406
|
+
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70407
|
+
color: theme.colors.muted,
|
|
70408
|
+
children: "┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈"
|
|
70409
|
+
}, undefined, false, undefined, this)
|
|
70410
|
+
}, undefined, false, undefined, this),
|
|
70411
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70412
|
+
marginTop: 1,
|
|
70413
|
+
flexDirection: "column",
|
|
70414
|
+
gap: 0,
|
|
70415
|
+
children: [
|
|
70416
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70417
|
+
children: [
|
|
70418
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70419
|
+
width: 12,
|
|
70420
|
+
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70421
|
+
color: theme.colors.accent,
|
|
70422
|
+
children: "⚡ Total"
|
|
70423
|
+
}, undefined, false, undefined, this)
|
|
70424
|
+
}, undefined, false, undefined, this),
|
|
70425
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(AnimatedValue, {
|
|
70426
|
+
value: metrics.total,
|
|
70427
|
+
suffix: "ms",
|
|
70428
|
+
color: theme.colors.white
|
|
70429
|
+
}, undefined, false, undefined, this)
|
|
70430
|
+
]
|
|
70431
|
+
}, undefined, true, undefined, this),
|
|
70432
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70433
|
+
children: [
|
|
70434
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70435
|
+
width: 12,
|
|
70436
|
+
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70437
|
+
color: theme.colors.accent,
|
|
70438
|
+
children: "\uD83D\uDCE6 Size"
|
|
70439
|
+
}, undefined, false, undefined, this)
|
|
70440
|
+
}, undefined, false, undefined, this),
|
|
70441
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70442
|
+
color: theme.colors.white,
|
|
70443
|
+
bold: true,
|
|
70444
|
+
children: formatBytes(metrics.contentLength)
|
|
70445
|
+
}, undefined, false, undefined, this)
|
|
70446
|
+
]
|
|
70447
|
+
}, undefined, true, undefined, this),
|
|
70448
|
+
metrics.contentLength > 0 && metrics.contentDownload > 0 && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70449
|
+
children: [
|
|
70450
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70451
|
+
width: 12,
|
|
70452
|
+
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70453
|
+
color: theme.colors.accent,
|
|
70454
|
+
children: "\uD83D\uDE80 Speed"
|
|
70455
|
+
}, undefined, false, undefined, this)
|
|
70456
|
+
}, undefined, false, undefined, this),
|
|
70457
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70458
|
+
color: theme.colors.success,
|
|
70459
|
+
bold: true,
|
|
70460
|
+
children: [
|
|
70461
|
+
formatBytes(metrics.contentLength / (metrics.contentDownload / 1000)),
|
|
70462
|
+
"/s"
|
|
70463
|
+
]
|
|
70464
|
+
}, undefined, true, undefined, this)
|
|
70465
|
+
]
|
|
70466
|
+
}, undefined, true, undefined, this)
|
|
70467
|
+
]
|
|
70468
|
+
}, undefined, true, undefined, this)
|
|
70469
|
+
]
|
|
70470
|
+
}, undefined, true, undefined, this);
|
|
70471
|
+
};
|
|
70472
|
+
|
|
70473
|
+
// src/ui/app/ui.tsx
|
|
70474
|
+
var jsx_dev_runtime13 = __toESM(require_jsx_dev_runtime(), 1);
|
|
70475
|
+
var formatBytes2 = (bytes) => {
|
|
70476
|
+
if (bytes === 0)
|
|
70477
|
+
return "0 B";
|
|
70478
|
+
const k = 1024;
|
|
70479
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
70480
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
70481
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
70482
|
+
};
|
|
70483
|
+
var LiveByteCounter = ({ progress, theme }) => {
|
|
70484
|
+
const [pulseFrame, setPulseFrame] = import_react35.useState(0);
|
|
70485
|
+
const pulseChars = ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"];
|
|
70486
|
+
const arrowFrames = ["↓", "⬇", "↓", "⇣"];
|
|
70487
|
+
import_react35.useEffect(() => {
|
|
70488
|
+
const interval = setInterval(() => {
|
|
70489
|
+
setPulseFrame((prev) => (prev + 1) % pulseChars.length);
|
|
70490
|
+
}, 100);
|
|
70491
|
+
return () => clearInterval(interval);
|
|
70492
|
+
}, []);
|
|
70493
|
+
if (!progress)
|
|
70494
|
+
return null;
|
|
70495
|
+
const { bytesReceived, totalBytes, speed } = progress;
|
|
70496
|
+
const percentage = totalBytes > 0 ? Math.round(bytesReceived / totalBytes * 100) : 0;
|
|
70497
|
+
const progressBarWidth = 20;
|
|
70498
|
+
const filledWidth = totalBytes > 0 ? Math.round(bytesReceived / totalBytes * progressBarWidth) : 0;
|
|
70499
|
+
const filledBar = "█".repeat(filledWidth);
|
|
70500
|
+
const emptyBar = "░".repeat(progressBarWidth - filledWidth);
|
|
70501
|
+
return /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70502
|
+
flexDirection: "column",
|
|
70503
|
+
paddingX: 1,
|
|
70504
|
+
paddingY: 1,
|
|
70505
|
+
borderStyle: "round",
|
|
70506
|
+
borderColor: theme.accent,
|
|
70507
|
+
children: [
|
|
70508
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70509
|
+
marginBottom: 1,
|
|
70510
|
+
children: [
|
|
70511
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70512
|
+
color: theme.accent,
|
|
70513
|
+
bold: true,
|
|
70514
|
+
children: [
|
|
70515
|
+
pulseChars[pulseFrame],
|
|
70516
|
+
" "
|
|
70517
|
+
]
|
|
70518
|
+
}, undefined, true, undefined, this),
|
|
70519
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70520
|
+
color: theme.primary,
|
|
70521
|
+
bold: true,
|
|
70522
|
+
children: "DOWNLOADING "
|
|
70523
|
+
}, undefined, false, undefined, this),
|
|
70524
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70525
|
+
color: theme.accent,
|
|
70526
|
+
children: arrowFrames[pulseFrame % arrowFrames.length]
|
|
70527
|
+
}, undefined, false, undefined, this)
|
|
70528
|
+
]
|
|
70529
|
+
}, undefined, true, undefined, this),
|
|
70530
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70531
|
+
children: [
|
|
70532
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70533
|
+
color: theme.success,
|
|
70534
|
+
children: filledBar
|
|
70535
|
+
}, undefined, false, undefined, this),
|
|
70536
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70537
|
+
color: theme.muted,
|
|
70538
|
+
dimColor: true,
|
|
70539
|
+
children: emptyBar
|
|
70540
|
+
}, undefined, false, undefined, this),
|
|
70541
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70542
|
+
color: theme.white,
|
|
70543
|
+
bold: true,
|
|
70544
|
+
children: [
|
|
70545
|
+
" ",
|
|
70546
|
+
percentage,
|
|
70547
|
+
"%"
|
|
70548
|
+
]
|
|
70549
|
+
}, undefined, true, undefined, this)
|
|
70550
|
+
]
|
|
70551
|
+
}, undefined, true, undefined, this),
|
|
70552
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70553
|
+
marginTop: 1,
|
|
70554
|
+
children: [
|
|
70555
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70556
|
+
marginRight: 2,
|
|
70557
|
+
children: [
|
|
70558
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70559
|
+
color: theme.accent,
|
|
70560
|
+
children: "\uD83D\uDCE6 "
|
|
70561
|
+
}, undefined, false, undefined, this),
|
|
70562
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70563
|
+
color: theme.white,
|
|
70564
|
+
bold: true,
|
|
70565
|
+
children: formatBytes2(bytesReceived)
|
|
70566
|
+
}, undefined, false, undefined, this),
|
|
70567
|
+
totalBytes > 0 && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70568
|
+
color: theme.muted,
|
|
70569
|
+
children: [
|
|
70570
|
+
" / ",
|
|
70571
|
+
formatBytes2(totalBytes)
|
|
70572
|
+
]
|
|
70573
|
+
}, undefined, true, undefined, this)
|
|
70574
|
+
]
|
|
70575
|
+
}, undefined, true, undefined, this),
|
|
70576
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70577
|
+
children: [
|
|
70578
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70579
|
+
color: theme.success,
|
|
70580
|
+
children: "\uD83D\uDE80 "
|
|
70581
|
+
}, undefined, false, undefined, this),
|
|
70582
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70583
|
+
color: theme.success,
|
|
70584
|
+
bold: true,
|
|
70585
|
+
children: [
|
|
70586
|
+
formatBytes2(speed),
|
|
70587
|
+
"/s"
|
|
70588
|
+
]
|
|
70589
|
+
}, undefined, true, undefined, this)
|
|
70590
|
+
]
|
|
70591
|
+
}, undefined, true, undefined, this)
|
|
70592
|
+
]
|
|
70593
|
+
}, undefined, true, undefined, this)
|
|
70594
|
+
]
|
|
70595
|
+
}, undefined, true, undefined, this);
|
|
70596
|
+
};
|
|
70597
|
+
var SendButton = ({ onPress, loading, theme }) => {
|
|
70598
|
+
const { isFocused } = use_focus_default();
|
|
70599
|
+
use_input_default((_, key) => {
|
|
70600
|
+
if (isFocused && key.return)
|
|
70601
|
+
onPress();
|
|
70602
|
+
});
|
|
70603
|
+
return /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70604
|
+
borderStyle: "round",
|
|
70605
|
+
paddingX: 2,
|
|
70606
|
+
borderTopDimColor: true,
|
|
70607
|
+
borderColor: isFocused ? theme.accent : theme.primary,
|
|
70608
|
+
children: loading ? /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Spinner, {
|
|
70609
|
+
theme
|
|
70610
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70611
|
+
bold: true,
|
|
70612
|
+
color: isFocused ? theme.accent : theme.white,
|
|
70613
|
+
children: "\uD83D\uDE80 Send"
|
|
70614
|
+
}, undefined, false, undefined, this)
|
|
70615
|
+
}, undefined, false, undefined, this);
|
|
70616
|
+
};
|
|
70617
|
+
var HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"];
|
|
70618
|
+
var RequestPanel = import_react35.default.memo(({ request, onMethodChange, onUrlChange, onHeadersChange, onBodyChange, onSend, loading, theme, historyUrls = [], onInputFocus }) => /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70619
|
+
flexDirection: "column",
|
|
70620
|
+
gap: 1,
|
|
70122
70621
|
flexGrow: 1,
|
|
70123
70622
|
children: [
|
|
70124
70623
|
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(FormField, {
|
|
@@ -70167,29 +70666,31 @@ var RequestPanel = import_react34.default.memo(({ request, onMethodChange, onUrl
|
|
|
70167
70666
|
]
|
|
70168
70667
|
}, undefined, true, undefined, this));
|
|
70169
70668
|
var UI = () => {
|
|
70170
|
-
const [theme, setTheme] =
|
|
70669
|
+
const [theme, setTheme] = import_react35.useState(themes.catppuccin);
|
|
70171
70670
|
const { exit } = use_app_default();
|
|
70172
|
-
const [activeTab, setActiveTab] =
|
|
70173
|
-
const [request, setRequest] =
|
|
70174
|
-
const [response, setResponse] =
|
|
70175
|
-
const [metrics, setMetrics] =
|
|
70176
|
-
const [history, setHistory] =
|
|
70177
|
-
const [loading, setLoading] =
|
|
70178
|
-
const
|
|
70671
|
+
const [activeTab, setActiveTab] = import_react35.useState("request");
|
|
70672
|
+
const [request, setRequest] = import_react35.useState({ method: "GET", url: "", headers: "", body: "" });
|
|
70673
|
+
const [response, setResponse] = import_react35.useState({ statustext: "", status: "", headers: "", body: "", error: "" });
|
|
70674
|
+
const [metrics, setMetrics] = import_react35.useState(null);
|
|
70675
|
+
const [history, setHistory] = import_react35.useState([]);
|
|
70676
|
+
const [loading, setLoading] = import_react35.useState(false);
|
|
70677
|
+
const [downloadProgress, setDownloadProgress] = import_react35.useState(null);
|
|
70678
|
+
const requestRef = import_react35.useRef(request);
|
|
70179
70679
|
requestRef.current = request;
|
|
70180
|
-
|
|
70680
|
+
import_react35.useEffect(() => {
|
|
70181
70681
|
const loadHistory = async () => setHistory((await historyManager.loadHistory()).entries);
|
|
70182
70682
|
loadHistory();
|
|
70183
70683
|
}, []);
|
|
70184
|
-
|
|
70684
|
+
import_react35.useEffect(() => {
|
|
70185
70685
|
const loadTheme = async () => {
|
|
70186
70686
|
const loadedTheme = await themeManager.loadCurrTheme();
|
|
70187
70687
|
setTheme(loadedTheme);
|
|
70188
70688
|
};
|
|
70189
70689
|
loadTheme();
|
|
70190
70690
|
}, []);
|
|
70191
|
-
const handleSend =
|
|
70691
|
+
const handleSend = import_react35.useCallback(async () => {
|
|
70192
70692
|
setLoading(true);
|
|
70693
|
+
setDownloadProgress(null);
|
|
70193
70694
|
const startTime = Date.now();
|
|
70194
70695
|
const currentRequest = requestRef.current;
|
|
70195
70696
|
try {
|
|
@@ -70211,7 +70712,8 @@ var UI = () => {
|
|
|
70211
70712
|
method: currentRequest.method,
|
|
70212
70713
|
url: currentRequest.url,
|
|
70213
70714
|
headers: parsedHeaders,
|
|
70214
|
-
body: reqBody
|
|
70715
|
+
body: reqBody,
|
|
70716
|
+
onProgress: (progress) => setDownloadProgress(progress)
|
|
70215
70717
|
});
|
|
70216
70718
|
const responseTime = Date.now() - startTime;
|
|
70217
70719
|
await historyManager.addEntry({ ...currentRequest }, res.status, responseTime);
|
|
@@ -70224,13 +70726,14 @@ var UI = () => {
|
|
|
70224
70726
|
setActiveTab("response");
|
|
70225
70727
|
} finally {
|
|
70226
70728
|
setLoading(false);
|
|
70729
|
+
setDownloadProgress(null);
|
|
70227
70730
|
}
|
|
70228
70731
|
}, []);
|
|
70229
70732
|
const handleThemeChange = (theme2) => {
|
|
70230
70733
|
themeManager.ChangeTheme(theme2);
|
|
70231
70734
|
setTheme(theme2);
|
|
70232
70735
|
};
|
|
70233
|
-
const handleHistoryClick =
|
|
70736
|
+
const handleHistoryClick = import_react35.useCallback((item) => {
|
|
70234
70737
|
setRequest({
|
|
70235
70738
|
method: item.method,
|
|
70236
70739
|
url: item.url,
|
|
@@ -70241,9 +70744,9 @@ var UI = () => {
|
|
|
70241
70744
|
}, []);
|
|
70242
70745
|
const tabs = [{ name: "request", label: "Request" }, { name: "response", label: "Response" }];
|
|
70243
70746
|
const activeIndex = tabs.findIndex((t) => t.name === activeTab);
|
|
70244
|
-
const [showThemeSelector, setShowThemeSelector] =
|
|
70245
|
-
const [showExportDialog, setShowExportDialog] =
|
|
70246
|
-
const [inputFocused, setInputFocused] =
|
|
70747
|
+
const [showThemeSelector, setShowThemeSelector] = import_react35.useState(false);
|
|
70748
|
+
const [showExportDialog, setShowExportDialog] = import_react35.useState(false);
|
|
70749
|
+
const [inputFocused, setInputFocused] = import_react35.useState(false);
|
|
70247
70750
|
use_input_default((input, key) => {
|
|
70248
70751
|
if (input === "q" && !showExportDialog)
|
|
70249
70752
|
exit();
|
|
@@ -70262,10 +70765,10 @@ var UI = () => {
|
|
|
70262
70765
|
if ((input === "e" || input === "E") && !key.ctrl && !key.meta && !inputFocused && !showThemeSelector)
|
|
70263
70766
|
setShowExportDialog((prev) => !prev);
|
|
70264
70767
|
}, { isActive: !showExportDialog });
|
|
70265
|
-
const onMethodChange =
|
|
70266
|
-
const onUrlChange =
|
|
70267
|
-
const onHeadersChange =
|
|
70268
|
-
const onBodyChange =
|
|
70768
|
+
const onMethodChange = import_react35.useCallback((method) => setRequest((r) => ({ ...r, method })), []);
|
|
70769
|
+
const onUrlChange = import_react35.useCallback((url) => setRequest((r) => ({ ...r, url })), []);
|
|
70770
|
+
const onHeadersChange = import_react35.useCallback((headers) => setRequest((r) => ({ ...r, headers })), []);
|
|
70771
|
+
const onBodyChange = import_react35.useCallback((body) => setRequest((r) => ({ ...r, body })), []);
|
|
70269
70772
|
const historyUrls = Array.from(new Set(history.map((h) => h.url))).filter(Boolean);
|
|
70270
70773
|
return /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70271
70774
|
padding: 1,
|
|
@@ -70370,6 +70873,27 @@ var UI = () => {
|
|
|
70370
70873
|
theme
|
|
70371
70874
|
}, undefined, false, undefined, this)
|
|
70372
70875
|
}, undefined, false, undefined, this),
|
|
70876
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70877
|
+
flexDirection: "column",
|
|
70878
|
+
borderStyle: "round",
|
|
70879
|
+
borderColor: theme.colors.muted,
|
|
70880
|
+
marginX: 1,
|
|
70881
|
+
children: [
|
|
70882
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70883
|
+
alignSelf: "center",
|
|
70884
|
+
paddingX: 1,
|
|
70885
|
+
children: /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70886
|
+
color: theme.colors.accent,
|
|
70887
|
+
bold: true,
|
|
70888
|
+
children: "⚡ Metrics"
|
|
70889
|
+
}, undefined, false, undefined, this)
|
|
70890
|
+
}, undefined, false, undefined, this),
|
|
70891
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(MetricsPanel, {
|
|
70892
|
+
metrics,
|
|
70893
|
+
theme
|
|
70894
|
+
}, undefined, false, undefined, this)
|
|
70895
|
+
]
|
|
70896
|
+
}, undefined, true, undefined, this),
|
|
70373
70897
|
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70374
70898
|
alignSelf: "center",
|
|
70375
70899
|
marginBottom: 1,
|
|
@@ -70402,6 +70926,14 @@ var UI = () => {
|
|
|
70402
70926
|
onChange: setActiveTab,
|
|
70403
70927
|
theme
|
|
70404
70928
|
}, undefined, false, undefined, this),
|
|
70929
|
+
downloadProgress && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70930
|
+
marginTop: 1,
|
|
70931
|
+
justifyContent: "center",
|
|
70932
|
+
children: /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(LiveByteCounter, {
|
|
70933
|
+
progress: downloadProgress,
|
|
70934
|
+
theme: theme.colors
|
|
70935
|
+
}, undefined, false, undefined, this)
|
|
70936
|
+
}, undefined, false, undefined, this),
|
|
70405
70937
|
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70406
70938
|
marginTop: 1,
|
|
70407
70939
|
flexDirection: "column",
|
|
@@ -70428,8 +70960,7 @@ var UI = () => {
|
|
|
70428
70960
|
flexGrow: 1,
|
|
70429
70961
|
children: /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(ResponsePanel, {
|
|
70430
70962
|
response,
|
|
70431
|
-
theme
|
|
70432
|
-
metrics
|
|
70963
|
+
theme
|
|
70433
70964
|
}, undefined, false, undefined, this)
|
|
70434
70965
|
}, undefined, false, undefined, this)
|
|
70435
70966
|
]
|
|
@@ -70651,7 +71182,7 @@ async function mockApis() {
|
|
|
70651
71182
|
|
|
70652
71183
|
// src/index.ts
|
|
70653
71184
|
var program2 = new Command;
|
|
70654
|
-
program2.version("1.
|
|
71185
|
+
program2.version("1.4.0").description(import_chalk9.default.yellow("PostBoy CLI - Test your APIs with ease"));
|
|
70655
71186
|
program2.command("run").description("Run a test API request").action(testCommand);
|
|
70656
71187
|
program2.command("mock-list").description("List the mock API servers").action(mockApis);
|
|
70657
71188
|
program2.command("ui").description("UI for PostBoy").action(uiCommand);
|