postboy-tui 1.3.2 → 1.3.4
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/README.md +4 -4
- package/dist/cli.js +84 -69
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ bun i -g postboy-tui@latest
|
|
|
67
67
|
|
|
68
68
|
### 1. Intuitive TUI
|
|
69
69
|
|
|
70
|
-
A clean, keyboard-driven interface designed for productivity. Navigate between panels, compose requests
|
|
70
|
+
A clean, keyboard-driven interface designed for productivity. Navigate between panels, compose requests and view responses without leaving your terminal.
|
|
71
71
|
|
|
72
72
|
<img width="1111" height="649" alt="image" src="https://github.com/user-attachments/assets/de940869-4bfe-4349-a1bd-2259d46f2fde" />
|
|
73
73
|
|
|
@@ -75,7 +75,7 @@ A clean, keyboard-driven interface designed for productivity. Navigate between p
|
|
|
75
75
|
|
|
76
76
|
### 2. Request Composer
|
|
77
77
|
|
|
78
|
-
Create and edit HTTP requests with support for all major methods. Add headers, body
|
|
78
|
+
Create and edit HTTP requests with support for all major methods. Add headers, body and query parameters with ease.
|
|
79
79
|
|
|
80
80
|
<img width="643" height="428" alt="image" src="https://github.com/user-attachments/assets/304c5903-f3c1-4470-85d2-39eebb184c63" />
|
|
81
81
|
|
|
@@ -84,7 +84,7 @@ Create and edit HTTP requests with support for all major methods. Add headers, b
|
|
|
84
84
|
|
|
85
85
|
### 3. History Management
|
|
86
86
|
|
|
87
|
-
Automatically saves every request you make. Browse, search
|
|
87
|
+
Automatically saves every request you make. Browse, search and re-run previous requests.
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
<img width="427" height="440" alt="image" src="https://github.com/user-attachments/assets/cf055710-5701-490c-bfc6-a9afbbea223d" />
|
|
@@ -94,7 +94,7 @@ Automatically saves every request you make. Browse, search, and re-run previous
|
|
|
94
94
|
|
|
95
95
|
### 4. Response Viewer
|
|
96
96
|
|
|
97
|
-
View responses in a pretty-printed format. Supports JSON, XML
|
|
97
|
+
View responses in a pretty-printed format. Supports JSON, XML and raw text. Syntax highlighting for easy reading.
|
|
98
98
|
|
|
99
99
|
<img width="646" height="692" alt="image" src="https://github.com/user-attachments/assets/d5c60702-c71e-410c-bfbd-2643f78403f3" />
|
|
100
100
|
|
package/dist/cli.js
CHANGED
|
@@ -4428,7 +4428,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
4428
4428
|
|
|
4429
4429
|
// node_modules/react/index.js
|
|
4430
4430
|
var require_react = __commonJS((exports, module) => {
|
|
4431
|
-
var react_development = __toESM(require_react_development()
|
|
4431
|
+
var react_development = __toESM(require_react_development());
|
|
4432
4432
|
if (false) {} else {
|
|
4433
4433
|
module.exports = react_development;
|
|
4434
4434
|
}
|
|
@@ -4873,7 +4873,7 @@ var require_scheduler_development = __commonJS((exports) => {
|
|
|
4873
4873
|
|
|
4874
4874
|
// node_modules/react-reconciler/node_modules/scheduler/index.js
|
|
4875
4875
|
var require_scheduler = __commonJS((exports, module) => {
|
|
4876
|
-
var scheduler_development = __toESM(require_scheduler_development()
|
|
4876
|
+
var scheduler_development = __toESM(require_scheduler_development());
|
|
4877
4877
|
if (false) {} else {
|
|
4878
4878
|
module.exports = scheduler_development;
|
|
4879
4879
|
}
|
|
@@ -4881,8 +4881,8 @@ var require_scheduler = __commonJS((exports, module) => {
|
|
|
4881
4881
|
|
|
4882
4882
|
// node_modules/react-reconciler/cjs/react-reconciler.development.js
|
|
4883
4883
|
var require_react_reconciler_development = __commonJS((exports, module) => {
|
|
4884
|
-
var React = __toESM(require_react()
|
|
4885
|
-
var Scheduler = __toESM(require_scheduler()
|
|
4884
|
+
var React = __toESM(require_react());
|
|
4885
|
+
var Scheduler = __toESM(require_scheduler());
|
|
4886
4886
|
module.exports = function($$$config) {
|
|
4887
4887
|
function findHook(fiber, id) {
|
|
4888
4888
|
for (fiber = fiber.memoizedState;fiber !== null && 0 < id; )
|
|
@@ -31695,7 +31695,7 @@ var require_stack_utils = __commonJS((exports, module) => {
|
|
|
31695
31695
|
|
|
31696
31696
|
// node_modules/react/cjs/react-jsx-dev-runtime.development.js
|
|
31697
31697
|
var require_react_jsx_dev_runtime_development = __commonJS((exports) => {
|
|
31698
|
-
var React10 = __toESM(require_react()
|
|
31698
|
+
var React10 = __toESM(require_react());
|
|
31699
31699
|
(function() {
|
|
31700
31700
|
function getComponentNameFromType(type) {
|
|
31701
31701
|
if (type == null)
|
|
@@ -31909,7 +31909,7 @@ React keys must be passed directly to JSX without using spread:
|
|
|
31909
31909
|
|
|
31910
31910
|
// node_modules/react/jsx-dev-runtime.js
|
|
31911
31911
|
var require_jsx_dev_runtime = __commonJS((exports, module) => {
|
|
31912
|
-
var react_jsx_dev_runtime_development = __toESM(require_react_jsx_dev_runtime_development()
|
|
31912
|
+
var react_jsx_dev_runtime_development = __toESM(require_react_jsx_dev_runtime_development());
|
|
31913
31913
|
if (false) {} else {
|
|
31914
31914
|
module.exports = react_jsx_dev_runtime_development;
|
|
31915
31915
|
}
|
|
@@ -67644,17 +67644,26 @@ function sendRequest({ method, url, headers = {}, body }) {
|
|
|
67644
67644
|
data += chunk;
|
|
67645
67645
|
});
|
|
67646
67646
|
res.on("end", () => {
|
|
67647
|
-
|
|
67648
|
-
|
|
67649
|
-
|
|
67650
|
-
|
|
67651
|
-
|
|
67652
|
-
|
|
67647
|
+
try {
|
|
67648
|
+
resolve({
|
|
67649
|
+
status: res.statusCode || 0,
|
|
67650
|
+
statusText: res.statusMessage || "",
|
|
67651
|
+
headers: Object.fromEntries(Object.entries(res.headers).map(([k, v]) => [k, Array.isArray(v) ? v.join(", ") : v || ""])),
|
|
67652
|
+
body: data
|
|
67653
|
+
});
|
|
67654
|
+
} catch (err) {
|
|
67655
|
+
reject(err);
|
|
67656
|
+
}
|
|
67653
67657
|
});
|
|
67654
67658
|
});
|
|
67655
67659
|
req.on("error", reject);
|
|
67656
|
-
if (body)
|
|
67657
|
-
|
|
67660
|
+
if (body) {
|
|
67661
|
+
try {
|
|
67662
|
+
req.write(body);
|
|
67663
|
+
} catch (err) {
|
|
67664
|
+
reject(err);
|
|
67665
|
+
}
|
|
67666
|
+
}
|
|
67658
67667
|
req.end();
|
|
67659
67668
|
});
|
|
67660
67669
|
}
|
|
@@ -67822,8 +67831,11 @@ var Spinner = ({ theme }) => {
|
|
|
67822
67831
|
// src/ui/app/components/Formfield.tsx
|
|
67823
67832
|
var import_react24 = __toESM(require_react(), 1);
|
|
67824
67833
|
var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
67825
|
-
var FormField = ({ label, value, onChange, placeholder, theme, suggestions = [] }) => {
|
|
67834
|
+
var FormField = ({ label, value, onChange, placeholder, theme, suggestions = [], onFocusChange }) => {
|
|
67826
67835
|
const { isFocused } = use_focus_default();
|
|
67836
|
+
import_react24.useEffect(() => {
|
|
67837
|
+
onFocusChange?.(isFocused);
|
|
67838
|
+
}, [isFocused, onFocusChange]);
|
|
67827
67839
|
const [showSuggestions, setShowSuggestions] = import_react24.useState(false);
|
|
67828
67840
|
const [filteredSuggestions, setFilteredSuggestions] = import_react24.useState([]);
|
|
67829
67841
|
const [highlightedIndex, setHighlightedIndex] = import_react24.useState(0);
|
|
@@ -68351,12 +68363,15 @@ var JsonSyntaxHighlight = import_react29.default.memo(({ jsonString, theme }) =>
|
|
|
68351
68363
|
// src/ui/app/components/responsepanel.tsx
|
|
68352
68364
|
var import_react30 = __toESM(require_react(), 1);
|
|
68353
68365
|
var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
|
|
68354
|
-
var ResponsePanel = import_react30.default.memo(({ response, theme }) =>
|
|
68355
|
-
|
|
68366
|
+
var ResponsePanel = import_react30.default.memo(({ response, theme }) => {
|
|
68367
|
+
const [activeTab, setActiveTab] = import_react30.useState("body");
|
|
68368
|
+
const tabs = [{ name: "headers", label: "Headers" }, { name: "body", label: "Body" }];
|
|
68369
|
+
return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
68356
68370
|
flexDirection: "column",
|
|
68357
|
-
|
|
68371
|
+
flexGrow: 1,
|
|
68358
68372
|
children: [
|
|
68359
68373
|
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
68374
|
+
marginBottom: 1,
|
|
68360
68375
|
children: [
|
|
68361
68376
|
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
68362
68377
|
width: 8,
|
|
@@ -68376,58 +68391,52 @@ var ResponsePanel = import_react30.default.memo(({ response, theme }) => /* @__P
|
|
|
68376
68391
|
}, undefined, true, undefined, this)
|
|
68377
68392
|
]
|
|
68378
68393
|
}, undefined, true, undefined, this),
|
|
68394
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Tabs, {
|
|
68395
|
+
tabs,
|
|
68396
|
+
activeTab,
|
|
68397
|
+
onChange: setActiveTab,
|
|
68398
|
+
theme
|
|
68399
|
+
}, undefined, false, undefined, this),
|
|
68379
68400
|
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
68401
|
+
marginTop: 1,
|
|
68402
|
+
flexGrow: 1,
|
|
68380
68403
|
children: [
|
|
68381
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(
|
|
68382
|
-
|
|
68383
|
-
|
|
68384
|
-
|
|
68385
|
-
|
|
68386
|
-
|
|
68387
|
-
|
|
68388
|
-
|
|
68389
|
-
|
|
68390
|
-
|
|
68391
|
-
|
|
68392
|
-
|
|
68393
|
-
|
|
68394
|
-
|
|
68395
|
-
|
|
68396
|
-
|
|
68397
|
-
|
|
68398
|
-
|
|
68399
|
-
|
|
68400
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
68401
|
-
color: theme.colors.success,
|
|
68402
|
-
children: String(value)
|
|
68403
|
-
}, undefined, false, undefined, this)
|
|
68404
|
-
]
|
|
68405
|
-
}, key, true, undefined, this))
|
|
68406
|
-
}, undefined, false, undefined, this)
|
|
68407
|
-
]
|
|
68408
|
-
}, undefined, true, undefined, this),
|
|
68409
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
68410
|
-
children: [
|
|
68411
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
68412
|
-
width: 8,
|
|
68413
|
-
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
68414
|
-
color: theme.colors.primary,
|
|
68415
|
-
children: "PAYLOAD:"
|
|
68404
|
+
activeTab === "headers" && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(ScrollableBox, {
|
|
68405
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
68406
|
+
flexDirection: "column",
|
|
68407
|
+
children: Object.entries(JSON.parse(response.headers || "{}")).map(([key, value]) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
68408
|
+
children: [
|
|
68409
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
68410
|
+
color: theme.colors.accent,
|
|
68411
|
+
children: key
|
|
68412
|
+
}, undefined, false, undefined, this),
|
|
68413
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
68414
|
+
color: theme.colors.muted,
|
|
68415
|
+
children: ": "
|
|
68416
|
+
}, undefined, false, undefined, this),
|
|
68417
|
+
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
|
|
68418
|
+
color: theme.colors.success,
|
|
68419
|
+
children: String(value)
|
|
68420
|
+
}, undefined, false, undefined, this)
|
|
68421
|
+
]
|
|
68422
|
+
}, key, true, undefined, this))
|
|
68416
68423
|
}, undefined, false, undefined, this)
|
|
68417
68424
|
}, undefined, false, undefined, this),
|
|
68418
|
-
/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(
|
|
68419
|
-
|
|
68420
|
-
|
|
68421
|
-
|
|
68422
|
-
|
|
68423
|
-
|
|
68425
|
+
activeTab === "body" && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(ScrollableBox, {
|
|
68426
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
|
|
68427
|
+
flexDirection: "column",
|
|
68428
|
+
flexGrow: 1,
|
|
68429
|
+
children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(JsonSyntaxHighlight, {
|
|
68430
|
+
jsonString: response.body,
|
|
68431
|
+
theme
|
|
68432
|
+
}, undefined, false, undefined, this)
|
|
68424
68433
|
}, undefined, false, undefined, this)
|
|
68425
68434
|
}, undefined, false, undefined, this)
|
|
68426
68435
|
]
|
|
68427
68436
|
}, undefined, true, undefined, this)
|
|
68428
68437
|
]
|
|
68429
|
-
}, undefined, true, undefined, this)
|
|
68430
|
-
}
|
|
68438
|
+
}, undefined, true, undefined, this);
|
|
68439
|
+
});
|
|
68431
68440
|
|
|
68432
68441
|
// src/utils/themeManager.ts
|
|
68433
68442
|
import { promises as fs3 } from "fs";
|
|
@@ -68554,7 +68563,7 @@ var SendButton = ({ onPress, loading, theme }) => {
|
|
|
68554
68563
|
}, undefined, false, undefined, this);
|
|
68555
68564
|
};
|
|
68556
68565
|
var HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"];
|
|
68557
|
-
var RequestPanel = import_react31.default.memo(({ request, onMethodChange, onUrlChange, onHeadersChange, onBodyChange, onSend, loading, theme, historyUrls = [] }) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
68566
|
+
var RequestPanel = import_react31.default.memo(({ request, onMethodChange, onUrlChange, onHeadersChange, onBodyChange, onSend, loading, theme, historyUrls = [], onInputFocus }) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
68558
68567
|
flexDirection: "column",
|
|
68559
68568
|
gap: 1,
|
|
68560
68569
|
flexGrow: 1,
|
|
@@ -68565,7 +68574,8 @@ var RequestPanel = import_react31.default.memo(({ request, onMethodChange, onUrl
|
|
|
68565
68574
|
onChange: onMethodChange,
|
|
68566
68575
|
placeholder: "GET",
|
|
68567
68576
|
theme,
|
|
68568
|
-
suggestions: HTTP_METHODS
|
|
68577
|
+
suggestions: HTTP_METHODS,
|
|
68578
|
+
onFocusChange: onInputFocus
|
|
68569
68579
|
}, undefined, false, undefined, this),
|
|
68570
68580
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(FormField, {
|
|
68571
68581
|
label: "URL",
|
|
@@ -68573,21 +68583,24 @@ var RequestPanel = import_react31.default.memo(({ request, onMethodChange, onUrl
|
|
|
68573
68583
|
onChange: onUrlChange,
|
|
68574
68584
|
placeholder: "https://api.example.com",
|
|
68575
68585
|
theme,
|
|
68576
|
-
suggestions: historyUrls
|
|
68586
|
+
suggestions: historyUrls,
|
|
68587
|
+
onFocusChange: onInputFocus
|
|
68577
68588
|
}, undefined, false, undefined, this),
|
|
68578
68589
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(FormField, {
|
|
68579
68590
|
label: "Headers",
|
|
68580
68591
|
value: request.headers,
|
|
68581
68592
|
onChange: onHeadersChange,
|
|
68582
68593
|
placeholder: '{ "key": "value" }',
|
|
68583
|
-
theme
|
|
68594
|
+
theme,
|
|
68595
|
+
onFocusChange: onInputFocus
|
|
68584
68596
|
}, undefined, false, undefined, this),
|
|
68585
68597
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(FormField, {
|
|
68586
68598
|
label: "Body",
|
|
68587
68599
|
value: request.body,
|
|
68588
68600
|
onChange: onBodyChange,
|
|
68589
68601
|
placeholder: '{ "key": "value" }',
|
|
68590
|
-
theme
|
|
68602
|
+
theme,
|
|
68603
|
+
onFocusChange: onInputFocus
|
|
68591
68604
|
}, undefined, false, undefined, this),
|
|
68592
68605
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
68593
68606
|
marginTop: 1,
|
|
@@ -68674,6 +68687,7 @@ var UI = () => {
|
|
|
68674
68687
|
const tabs = [{ name: "request", label: "Request" }, { name: "response", label: "Response" }];
|
|
68675
68688
|
const activeIndex = tabs.findIndex((t) => t.name === activeTab);
|
|
68676
68689
|
const [showThemeSelector, setShowThemeSelector] = import_react31.useState(false);
|
|
68690
|
+
const [inputFocused, setInputFocused] = import_react31.useState(false);
|
|
68677
68691
|
use_input_default((input, key) => {
|
|
68678
68692
|
if (input === "q")
|
|
68679
68693
|
exit();
|
|
@@ -68685,7 +68699,7 @@ var UI = () => {
|
|
|
68685
68699
|
setActiveTab(tabs[(activeIndex - 1 + tabs.length) % tabs.length]?.name ?? "request");
|
|
68686
68700
|
if (key.escape && showThemeSelector)
|
|
68687
68701
|
setShowThemeSelector(false);
|
|
68688
|
-
if ((input === "t" || input === "T") && !key.ctrl && !key.meta)
|
|
68702
|
+
if ((input === "t" || input === "T") && !key.ctrl && !key.meta && !inputFocused)
|
|
68689
68703
|
setShowThemeSelector((prev) => !prev);
|
|
68690
68704
|
}, { isActive: true });
|
|
68691
68705
|
const onMethodChange = import_react31.useCallback((method) => setRequest((r) => ({ ...r, method })), []);
|
|
@@ -68835,7 +68849,8 @@ var UI = () => {
|
|
|
68835
68849
|
onSend: handleSend,
|
|
68836
68850
|
loading,
|
|
68837
68851
|
theme: theme.colors,
|
|
68838
|
-
historyUrls
|
|
68852
|
+
historyUrls,
|
|
68853
|
+
onInputFocus: setInputFocused
|
|
68839
68854
|
}, undefined, false, undefined, this)
|
|
68840
68855
|
}, undefined, false, undefined, this),
|
|
68841
68856
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
@@ -69065,7 +69080,7 @@ async function mockApis() {
|
|
|
69065
69080
|
|
|
69066
69081
|
// src/index.ts
|
|
69067
69082
|
var program2 = new Command;
|
|
69068
|
-
program2.version("1.3.
|
|
69083
|
+
program2.version("1.3.4").description(import_chalk8.default.yellow("PostBoy CLI - Test your APIs with ease"));
|
|
69069
69084
|
program2.command("run").description("Run a test API request").action(testCommand);
|
|
69070
69085
|
program2.command("mock-list").description("List the mock API servers").action(mockApis);
|
|
69071
69086
|
program2.command("ui").description("UI for PostBoy").action(uiCommand);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postboy-tui",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.4",
|
|
4
4
|
"main": "dist/cli.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"postboy-tui": "dist/cli.js"
|
|
@@ -8,22 +8,22 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"dist"
|
|
10
10
|
],
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
"keywords": [
|
|
12
|
+
"postboy",
|
|
13
|
+
"tui",
|
|
14
|
+
"cli",
|
|
15
|
+
"terminal",
|
|
16
|
+
"interface",
|
|
17
|
+
"developer-tool",
|
|
18
|
+
"api-testing"
|
|
19
|
+
],
|
|
20
20
|
"scripts": {
|
|
21
21
|
"start": "bun run src/index.ts",
|
|
22
22
|
"build": "bun build src/index.ts --outfile=dist/cli.js --target node",
|
|
23
23
|
"dev": "bun run --watch src/index.ts"
|
|
24
24
|
},
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
"repository": "https://github.com/Postboy-tui/app",
|
|
26
|
+
"homepage": "httsps://github.com/Postboy-tui/app#readme",
|
|
27
27
|
"module": "src/index.ts",
|
|
28
28
|
"type": "module",
|
|
29
29
|
"private": false,
|