@townco/cli 0.1.33 → 0.1.34
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.
|
@@ -39,7 +39,6 @@ export function MergedLogsPane({ services, onClear }) {
|
|
|
39
39
|
const [searchQuery, setSearchQuery] = useState("");
|
|
40
40
|
const [serviceFilter, setServiceFilter] = useState(null);
|
|
41
41
|
const [levelFilter, setLevelFilter] = useState(null);
|
|
42
|
-
const maxLines = 25;
|
|
43
42
|
// Only include services that actually have output
|
|
44
43
|
const availableServices = useMemo(() => services.filter((s) => s.output.length > 0).map((s) => s.service), [services]);
|
|
45
44
|
// Clear service filter if the selected service is no longer available
|
|
@@ -153,16 +152,13 @@ export function MergedLogsPane({ services, onClear }) {
|
|
|
153
152
|
return levelFilteredLines.filter((log) => fuzzyMatch(searchQuery, log.line));
|
|
154
153
|
}, [levelFilteredLines, searchQuery]);
|
|
155
154
|
const isAtBottom = scrollOffset === 0;
|
|
156
|
-
//
|
|
155
|
+
// Show all lines - no truncation
|
|
157
156
|
const displayLines = useMemo(() => {
|
|
158
157
|
if (isAtBottom) {
|
|
159
|
-
return searchedLines
|
|
158
|
+
return searchedLines; // Show all logs when at bottom
|
|
160
159
|
}
|
|
161
|
-
return searchedLines.slice(
|
|
160
|
+
return searchedLines.slice(0, searchedLines.length - scrollOffset);
|
|
162
161
|
}, [searchedLines, scrollOffset, isAtBottom]);
|
|
163
|
-
const _canScrollUp = searchedLines.length > maxLines &&
|
|
164
|
-
scrollOffset < searchedLines.length - maxLines;
|
|
165
|
-
const _canScrollDown = scrollOffset > 0;
|
|
166
162
|
// Get overall status (error if any error, stopped if all stopped, etc.)
|
|
167
163
|
const overallStatus = useMemo(() => {
|
|
168
164
|
if (services.some((s) => s.status === "error"))
|
|
@@ -20,7 +20,6 @@ export function ProcessPane({ title, output, port, status, onClear, }) {
|
|
|
20
20
|
const [scrollOffset, setScrollOffset] = useState(0); // 0 = at bottom, positive = scrolled up
|
|
21
21
|
const [searchMode, setSearchMode] = useState(false);
|
|
22
22
|
const [searchQuery, setSearchQuery] = useState("");
|
|
23
|
-
const maxLines = 25;
|
|
24
23
|
// Handle keyboard input for scrolling, clearing, and search
|
|
25
24
|
useInput((input, key) => {
|
|
26
25
|
// '/' to enter search mode
|
|
@@ -45,7 +44,7 @@ export function ProcessPane({ title, output, port, status, onClear, }) {
|
|
|
45
44
|
}
|
|
46
45
|
// Up arrow to scroll up
|
|
47
46
|
if (key.upArrow) {
|
|
48
|
-
setScrollOffset((prev) => Math.min(prev + 1,
|
|
47
|
+
setScrollOffset((prev) => Math.min(prev + 1, output.length - 1));
|
|
49
48
|
return;
|
|
50
49
|
}
|
|
51
50
|
// Down arrow to scroll down
|
|
@@ -69,16 +68,14 @@ export function ProcessPane({ title, output, port, status, onClear, }) {
|
|
|
69
68
|
return output;
|
|
70
69
|
return output.filter((line) => fuzzyMatch(searchQuery, line));
|
|
71
70
|
}, [output, searchQuery]);
|
|
72
|
-
//
|
|
71
|
+
// Show all lines - no truncation
|
|
73
72
|
const displayOutput = useMemo(() => {
|
|
74
|
-
const source = searchedOutput;
|
|
75
73
|
if (isAtBottom) {
|
|
76
|
-
return
|
|
74
|
+
return searchedOutput; // Show all logs when at bottom
|
|
77
75
|
}
|
|
78
|
-
return
|
|
76
|
+
return searchedOutput.slice(0, searchedOutput.length - scrollOffset);
|
|
79
77
|
}, [searchedOutput, scrollOffset, isAtBottom]);
|
|
80
|
-
const canScrollUp = searchedOutput.length
|
|
81
|
-
scrollOffset < searchedOutput.length - maxLines;
|
|
78
|
+
const canScrollUp = scrollOffset < searchedOutput.length - 1;
|
|
82
79
|
const canScrollDown = scrollOffset > 0;
|
|
83
80
|
const statusColor = status === "running"
|
|
84
81
|
? "green"
|
|
@@ -87,5 +84,5 @@ export function ProcessPane({ title, output, port, status, onClear, }) {
|
|
|
87
84
|
: status === "starting"
|
|
88
85
|
? "yellow"
|
|
89
86
|
: "gray";
|
|
90
|
-
return (_jsxs(Box, { flexDirection: "column", height: "100%", children: [_jsxs(Box, { borderStyle: "single", paddingX: 1, marginBottom: 1, flexShrink: 0, justifyContent: "space-between", children: [_jsxs(Box, { children: [_jsx(Text, { color: "cyan", bold: true, children: title }), port && _jsxs(Text, { color: "gray", children: [" - http://localhost:", port] }), _jsx(Text, { children: " " }), _jsx(Text, { color: statusColor, children: "\u25CF" }), _jsxs(Text, { children: [" ", status] }), searchQuery && _jsxs(Text, { color: "cyan", children: [" [SEARCH: ", searchQuery, "]"] }), !isAtBottom && _jsx(Text, { color: "yellow", children: " [SCROLLED]" })] }), _jsx(Text, { color: "gray", children: "(/)search | \u2191\u2193 | (c)lear | ESC" })] }), searchMode && (_jsxs(Box, { borderStyle: "single", borderBottom: true, borderColor: "cyan", paddingX: 1, marginBottom: 1, flexShrink: 0, children: [_jsx(Text, { color: "cyan", children: "Search: " }), _jsx(TextInput, { value: searchQuery, onChange: setSearchQuery, placeholder: "Type to search..." }), _jsx(Text, { dimColor: true, children: " (ESC to exit)" })] })), _jsx(Box, { flexDirection: "column", flexGrow: 1, minHeight: 0, paddingX: 1, children: displayOutput.length === 0 ? (_jsx(Text, { color: "gray", children: "Waiting for output..." })) : (displayOutput.map((line, idx) => (_jsx(Text, { children: line }, `${idx}-${line.slice(0, 20)}`)))) }), _jsxs(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, flexShrink: 0, justifyContent: "space-between", children: [_jsxs(Text, { color: "gray", children: ["Showing ", displayOutput.length, " of ", searchedOutput.length, " lines", searchQuery && ` (${searchedOutput.length} matches)`, scrollOffset > 0 && ` (${scrollOffset} from bottom)`] }),
|
|
87
|
+
return (_jsxs(Box, { flexDirection: "column", height: "100%", children: [_jsxs(Box, { borderStyle: "single", paddingX: 1, marginBottom: 1, flexShrink: 0, justifyContent: "space-between", children: [_jsxs(Box, { children: [_jsx(Text, { color: "cyan", bold: true, children: title }), port && _jsxs(Text, { color: "gray", children: [" - http://localhost:", port] }), _jsx(Text, { children: " " }), _jsx(Text, { color: statusColor, children: "\u25CF" }), _jsxs(Text, { children: [" ", status] }), searchQuery && _jsxs(Text, { color: "cyan", children: [" [SEARCH: ", searchQuery, "]"] }), !isAtBottom && _jsx(Text, { color: "yellow", children: " [SCROLLED]" })] }), _jsx(Text, { color: "gray", children: "(/)search | \u2191\u2193 | (c)lear | ESC" })] }), searchMode && (_jsxs(Box, { borderStyle: "single", borderBottom: true, borderColor: "cyan", paddingX: 1, marginBottom: 1, flexShrink: 0, children: [_jsx(Text, { color: "cyan", children: "Search: " }), _jsx(TextInput, { value: searchQuery, onChange: setSearchQuery, placeholder: "Type to search..." }), _jsx(Text, { dimColor: true, children: " (ESC to exit)" })] })), _jsx(Box, { flexDirection: "column", flexGrow: 1, minHeight: 0, paddingX: 1, children: displayOutput.length === 0 ? (_jsx(Text, { color: "gray", children: "Waiting for output..." })) : (displayOutput.map((line, idx) => (_jsx(Text, { children: line }, `${idx}-${line.slice(0, 20)}`)))) }), _jsxs(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, flexShrink: 0, justifyContent: "space-between", children: [_jsxs(Text, { color: "gray", children: ["Showing ", displayOutput.length, " of ", searchedOutput.length, " lines", searchQuery && ` (${searchedOutput.length} matches)`, scrollOffset > 0 && ` (${scrollOffset} from bottom)`] }), (canScrollUp || canScrollDown) && (_jsxs(Text, { color: "gray", children: [canScrollUp && "↑ ", canScrollDown && "↓"] }))] })] }));
|
|
91
88
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@townco/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.34",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"town": "./dist/index.js"
|
|
@@ -15,17 +15,17 @@
|
|
|
15
15
|
"build": "tsc"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@townco/tsconfig": "0.1.
|
|
18
|
+
"@townco/tsconfig": "0.1.26",
|
|
19
19
|
"@types/bun": "^1.3.1",
|
|
20
20
|
"@types/react": "^19.2.2"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@optique/core": "^0.6.2",
|
|
24
24
|
"@optique/run": "^0.6.2",
|
|
25
|
-
"@townco/agent": "0.1.
|
|
26
|
-
"@townco/core": "0.0.
|
|
27
|
-
"@townco/secret": "0.1.
|
|
28
|
-
"@townco/ui": "0.1.
|
|
25
|
+
"@townco/agent": "0.1.34",
|
|
26
|
+
"@townco/core": "0.0.7",
|
|
27
|
+
"@townco/secret": "0.1.29",
|
|
28
|
+
"@townco/ui": "0.1.29",
|
|
29
29
|
"@types/inquirer": "^9.0.9",
|
|
30
30
|
"ink": "^6.4.0",
|
|
31
31
|
"ink-text-input": "^6.0.0",
|