projax 3.3.67 → 3.3.68
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/prxi.js +53 -7
- package/dist/prxi.tsx +52 -6
- package/package.json +19 -20
package/dist/prxi.js
CHANGED
|
@@ -816,6 +816,7 @@ const App = () => {
|
|
|
816
816
|
const [showTerminalPanel, setShowTerminalPanel] = (0, react_1.useState)(false);
|
|
817
817
|
const [terminalLogs, setTerminalLogs] = (0, react_1.useState)([]);
|
|
818
818
|
const [selectedProcessPid, setSelectedProcessPid] = (0, react_1.useState)(null);
|
|
819
|
+
const [selectedProcessIndex, setSelectedProcessIndex] = (0, react_1.useState)(0);
|
|
819
820
|
// Settings state
|
|
820
821
|
const [settings, setSettings] = (0, react_1.useState)({
|
|
821
822
|
editor: { type: 'vscode' },
|
|
@@ -984,6 +985,15 @@ const App = () => {
|
|
|
984
985
|
(0, react_1.useEffect)(() => {
|
|
985
986
|
applyFilterAndSort(allProjects, searchQuery, filterType, sortType);
|
|
986
987
|
}, [filterType, sortType, runningProcesses]);
|
|
988
|
+
// Reset/clamp selectedProcessIndex when processes change
|
|
989
|
+
(0, react_1.useEffect)(() => {
|
|
990
|
+
if (runningProcesses.length === 0) {
|
|
991
|
+
setSelectedProcessIndex(0);
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
setSelectedProcessIndex((prev) => Math.min(prev, runningProcesses.length - 1));
|
|
995
|
+
}
|
|
996
|
+
}, [runningProcesses.length]);
|
|
987
997
|
const loadRunningProcesses = async () => {
|
|
988
998
|
try {
|
|
989
999
|
const processes = await (0, script_runner_1.getRunningProcessesClean)();
|
|
@@ -1310,10 +1320,38 @@ const App = () => {
|
|
|
1310
1320
|
}
|
|
1311
1321
|
// Handle navigation in processes view
|
|
1312
1322
|
if (currentView === 'processes') {
|
|
1323
|
+
if (key.upArrow || input === 'k') {
|
|
1324
|
+
setSelectedProcessIndex((prev) => Math.max(0, prev - 1));
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
if (key.downArrow || input === 'j') {
|
|
1328
|
+
setSelectedProcessIndex((prev) => Math.min(runningProcesses.length - 1, prev + 1));
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1313
1331
|
if (input === 'x' && runningProcesses.length > 0) {
|
|
1314
|
-
// Stop
|
|
1332
|
+
// Stop the selected process
|
|
1333
|
+
const selectedProc = runningProcesses[selectedProcessIndex];
|
|
1334
|
+
if (!selectedProc)
|
|
1335
|
+
return;
|
|
1336
|
+
setIsLoading(true);
|
|
1337
|
+
setLoadingMessage(`Stopping process ${selectedProc.pid}...`);
|
|
1338
|
+
setTimeout(async () => {
|
|
1339
|
+
try {
|
|
1340
|
+
await (0, script_runner_1.stopScript)(selectedProc.pid);
|
|
1341
|
+
await loadRunningProcesses();
|
|
1342
|
+
setIsLoading(false);
|
|
1343
|
+
}
|
|
1344
|
+
catch (err) {
|
|
1345
|
+
setIsLoading(false);
|
|
1346
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
1347
|
+
}
|
|
1348
|
+
}, 100);
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
if (input === 'X' && runningProcesses.length > 0) {
|
|
1352
|
+
// Stop ALL processes
|
|
1315
1353
|
setIsLoading(true);
|
|
1316
|
-
setLoadingMessage('Stopping processes...');
|
|
1354
|
+
setLoadingMessage('Stopping all processes...');
|
|
1317
1355
|
setTimeout(async () => {
|
|
1318
1356
|
try {
|
|
1319
1357
|
for (const proc of runningProcesses) {
|
|
@@ -1846,19 +1884,24 @@ const App = () => {
|
|
|
1846
1884
|
// Ignore workspace loading errors
|
|
1847
1885
|
}
|
|
1848
1886
|
};
|
|
1849
|
-
// Render Processes view
|
|
1887
|
+
// Render Processes view
|
|
1850
1888
|
const renderProcessesView = () => (react_1.default.createElement(ink_1.Box, { flexDirection: "column", padding: 2 },
|
|
1851
1889
|
react_1.default.createElement(ink_1.Text, { bold: true, color: colors.accentCyan },
|
|
1852
1890
|
"Running Processes (",
|
|
1853
1891
|
runningProcesses.length,
|
|
1854
1892
|
")"),
|
|
1855
1893
|
react_1.default.createElement(ink_1.Text, null, " "),
|
|
1856
|
-
runningProcesses.length === 0 ? (react_1.default.createElement(ink_1.Text, { color: colors.textTertiary }, "No running processes")) : (runningProcesses.map((proc) => {
|
|
1894
|
+
runningProcesses.length === 0 ? (react_1.default.createElement(ink_1.Text, { color: colors.textTertiary }, "No running processes")) : (runningProcesses.map((proc, index) => {
|
|
1857
1895
|
const uptime = Math.floor((Date.now() - proc.startedAt) / 1000);
|
|
1858
1896
|
const minutes = Math.floor(uptime / 60);
|
|
1859
1897
|
const seconds = uptime % 60;
|
|
1860
1898
|
const uptimeStr = minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
|
|
1861
|
-
|
|
1899
|
+
const isSelected = index === selectedProcessIndex;
|
|
1900
|
+
const portsStr = proc.detectedPorts && proc.detectedPorts.length > 0
|
|
1901
|
+
? ` [ports: ${proc.detectedPorts.join(', ')}]`
|
|
1902
|
+
: '';
|
|
1903
|
+
return (react_1.default.createElement(ink_1.Text, { key: proc.pid, color: isSelected ? colors.accentCyan : colors.textPrimary, bold: isSelected },
|
|
1904
|
+
isSelected ? '> ' : ' ',
|
|
1862
1905
|
react_1.default.createElement(ink_1.Text, { color: colors.accentGreen }, "\u25CF"),
|
|
1863
1906
|
" PID ",
|
|
1864
1907
|
proc.pid,
|
|
@@ -1867,10 +1910,13 @@ const App = () => {
|
|
|
1867
1910
|
" (",
|
|
1868
1911
|
proc.scriptName,
|
|
1869
1912
|
") - ",
|
|
1870
|
-
uptimeStr
|
|
1913
|
+
uptimeStr,
|
|
1914
|
+
portsStr && react_1.default.createElement(ink_1.Text, { color: colors.accentCyan }, portsStr)));
|
|
1871
1915
|
})),
|
|
1872
1916
|
react_1.default.createElement(ink_1.Text, null, " "),
|
|
1873
|
-
react_1.default.createElement(ink_1.Text, { color: colors.textTertiary },
|
|
1917
|
+
react_1.default.createElement(ink_1.Text, { color: colors.textTertiary }, runningProcesses.length > 0
|
|
1918
|
+
? 'up/down: navigate | x: stop selected | X: stop all | 1: back to projects'
|
|
1919
|
+
: 'Press 1 to return to Projects')));
|
|
1874
1920
|
// Render Settings view
|
|
1875
1921
|
const renderSettingsView = () => {
|
|
1876
1922
|
const currentOptions = settingsSection === 'editor' ? settingsEditorOptions : settingsBrowserOptions;
|
package/dist/prxi.tsx
CHANGED
|
@@ -1191,6 +1191,7 @@ const App: React.FC = () => {
|
|
|
1191
1191
|
const [showTerminalPanel, setShowTerminalPanel] = useState(false);
|
|
1192
1192
|
const [terminalLogs, setTerminalLogs] = useState<string[]>([]);
|
|
1193
1193
|
const [selectedProcessPid, setSelectedProcessPid] = useState<number | null>(null);
|
|
1194
|
+
const [selectedProcessIndex, setSelectedProcessIndex] = useState(0);
|
|
1194
1195
|
|
|
1195
1196
|
// Settings state
|
|
1196
1197
|
const [settings, setSettings] = useState<AppSettings>({
|
|
@@ -1382,6 +1383,15 @@ const App: React.FC = () => {
|
|
|
1382
1383
|
applyFilterAndSort(allProjects, searchQuery, filterType, sortType);
|
|
1383
1384
|
}, [filterType, sortType, runningProcesses]);
|
|
1384
1385
|
|
|
1386
|
+
// Reset/clamp selectedProcessIndex when processes change
|
|
1387
|
+
useEffect(() => {
|
|
1388
|
+
if (runningProcesses.length === 0) {
|
|
1389
|
+
setSelectedProcessIndex(0);
|
|
1390
|
+
} else {
|
|
1391
|
+
setSelectedProcessIndex((prev) => Math.min(prev, runningProcesses.length - 1));
|
|
1392
|
+
}
|
|
1393
|
+
}, [runningProcesses.length]);
|
|
1394
|
+
|
|
1385
1395
|
const loadRunningProcesses = async () => {
|
|
1386
1396
|
try {
|
|
1387
1397
|
const processes = await getRunningProcessesClean();
|
|
@@ -1733,10 +1743,36 @@ const App: React.FC = () => {
|
|
|
1733
1743
|
|
|
1734
1744
|
// Handle navigation in processes view
|
|
1735
1745
|
if (currentView === 'processes') {
|
|
1746
|
+
if (key.upArrow || input === 'k') {
|
|
1747
|
+
setSelectedProcessIndex((prev) => Math.max(0, prev - 1));
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
if (key.downArrow || input === 'j') {
|
|
1751
|
+
setSelectedProcessIndex((prev) => Math.min(runningProcesses.length - 1, prev + 1));
|
|
1752
|
+
return;
|
|
1753
|
+
}
|
|
1736
1754
|
if (input === 'x' && runningProcesses.length > 0) {
|
|
1737
|
-
// Stop
|
|
1755
|
+
// Stop the selected process
|
|
1756
|
+
const selectedProc = runningProcesses[selectedProcessIndex];
|
|
1757
|
+
if (!selectedProc) return;
|
|
1758
|
+
setIsLoading(true);
|
|
1759
|
+
setLoadingMessage(`Stopping process ${selectedProc.pid}...`);
|
|
1760
|
+
setTimeout(async () => {
|
|
1761
|
+
try {
|
|
1762
|
+
await stopScript(selectedProc.pid);
|
|
1763
|
+
await loadRunningProcesses();
|
|
1764
|
+
setIsLoading(false);
|
|
1765
|
+
} catch (err) {
|
|
1766
|
+
setIsLoading(false);
|
|
1767
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
1768
|
+
}
|
|
1769
|
+
}, 100);
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
if (input === 'X' && runningProcesses.length > 0) {
|
|
1773
|
+
// Stop ALL processes
|
|
1738
1774
|
setIsLoading(true);
|
|
1739
|
-
setLoadingMessage('Stopping processes...');
|
|
1775
|
+
setLoadingMessage('Stopping all processes...');
|
|
1740
1776
|
setTimeout(async () => {
|
|
1741
1777
|
try {
|
|
1742
1778
|
for (const proc of runningProcesses) {
|
|
@@ -2439,7 +2475,7 @@ const App: React.FC = () => {
|
|
|
2439
2475
|
}
|
|
2440
2476
|
};
|
|
2441
2477
|
|
|
2442
|
-
// Render Processes view
|
|
2478
|
+
// Render Processes view
|
|
2443
2479
|
const renderProcessesView = () => (
|
|
2444
2480
|
<Box flexDirection="column" padding={2}>
|
|
2445
2481
|
<Text bold color={colors.accentCyan}>Running Processes ({runningProcesses.length})</Text>
|
|
@@ -2447,20 +2483,30 @@ const App: React.FC = () => {
|
|
|
2447
2483
|
{runningProcesses.length === 0 ? (
|
|
2448
2484
|
<Text color={colors.textTertiary}>No running processes</Text>
|
|
2449
2485
|
) : (
|
|
2450
|
-
runningProcesses.map((proc: any) => {
|
|
2486
|
+
runningProcesses.map((proc: any, index: number) => {
|
|
2451
2487
|
const uptime = Math.floor((Date.now() - proc.startedAt) / 1000);
|
|
2452
2488
|
const minutes = Math.floor(uptime / 60);
|
|
2453
2489
|
const seconds = uptime % 60;
|
|
2454
2490
|
const uptimeStr = minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
|
|
2491
|
+
const isSelected = index === selectedProcessIndex;
|
|
2492
|
+
const portsStr = proc.detectedPorts && proc.detectedPorts.length > 0
|
|
2493
|
+
? ` [ports: ${proc.detectedPorts.join(', ')}]`
|
|
2494
|
+
: '';
|
|
2455
2495
|
return (
|
|
2456
|
-
<Text key={proc.pid} color={colors.textPrimary}>
|
|
2496
|
+
<Text key={proc.pid} color={isSelected ? colors.accentCyan : colors.textPrimary} bold={isSelected}>
|
|
2497
|
+
{isSelected ? '> ' : ' '}
|
|
2457
2498
|
<Text color={colors.accentGreen}>●</Text> PID {proc.pid}: {proc.projectName} ({proc.scriptName}) - {uptimeStr}
|
|
2499
|
+
{portsStr && <Text color={colors.accentCyan}>{portsStr}</Text>}
|
|
2458
2500
|
</Text>
|
|
2459
2501
|
);
|
|
2460
2502
|
})
|
|
2461
2503
|
)}
|
|
2462
2504
|
<Text> </Text>
|
|
2463
|
-
<Text color={colors.textTertiary}>
|
|
2505
|
+
<Text color={colors.textTertiary}>
|
|
2506
|
+
{runningProcesses.length > 0
|
|
2507
|
+
? 'up/down: navigate | x: stop selected | X: stop all | 1: back to projects'
|
|
2508
|
+
: 'Press 1 to return to Projects'}
|
|
2509
|
+
</Text>
|
|
2464
2510
|
</Box>
|
|
2465
2511
|
);
|
|
2466
2512
|
|
package/package.json
CHANGED
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projax",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.68",
|
|
4
4
|
"description": "Cross-platform project management dashboard for tracking local development projects. Features CLI, Terminal UI, Desktop app, REST API, and built-in tools for test detection, port management, and script execution.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"prx": "./dist/index.js"
|
|
8
8
|
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"build": "tsc",
|
|
11
|
-
"typecheck": "echo \"Skipping cli typecheck (legacy)\"",
|
|
12
|
-
"lint": "echo \"Skipping cli lint (not configured)\"",
|
|
13
|
-
"lint:fix": "echo \"Skipping cli lint (not configured)\"",
|
|
14
|
-
"build:electron": "cd ../desktop && pnpm run build",
|
|
15
|
-
"copy:electron": "mkdir -p dist/electron && cp -r ../desktop/dist/* dist/electron/ && cp dist/script-runner.* dist/electron/ && cp dist/port-*.* dist/electron/ && cp -R dist/core dist/electron/",
|
|
16
|
-
"copy:api": "mkdir -p dist/api && cp -r ../api/dist/* dist/api/ && cp ../api/package.json dist/api/",
|
|
17
|
-
"copy:core": "mkdir -p dist/core && cp -r ../core/dist/* dist/core/",
|
|
18
|
-
"copy:prxi": "cp src/prxi.tsx dist/prxi.tsx",
|
|
19
|
-
"build:all": "pnpm run build && pnpm run copy:core && pnpm run build:electron && pnpm run copy:electron && pnpm run copy:api && pnpm run copy:prxi",
|
|
20
|
-
"clean": "rm -rf dist",
|
|
21
|
-
"test": "jest",
|
|
22
|
-
"test:watch": "jest --watch",
|
|
23
|
-
"test:coverage": "jest --coverage",
|
|
24
|
-
"prepublishOnly": "pnpm run build:all"
|
|
25
|
-
},
|
|
26
9
|
"dependencies": {
|
|
27
10
|
"chokidar": "^3.6.0",
|
|
28
11
|
"commander": "^11.1.0",
|
|
@@ -74,5 +57,21 @@
|
|
|
74
57
|
},
|
|
75
58
|
"homepage": "https://projax.dev",
|
|
76
59
|
"author": "",
|
|
77
|
-
"license": "MIT"
|
|
78
|
-
|
|
60
|
+
"license": "MIT",
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "tsc",
|
|
63
|
+
"typecheck": "echo \"Skipping cli typecheck (legacy)\"",
|
|
64
|
+
"lint": "echo \"Skipping cli lint (not configured)\"",
|
|
65
|
+
"lint:fix": "echo \"Skipping cli lint (not configured)\"",
|
|
66
|
+
"build:electron": "cd ../desktop && pnpm run build",
|
|
67
|
+
"copy:electron": "mkdir -p dist/electron && cp -r ../desktop/dist/* dist/electron/ && cp dist/script-runner.* dist/electron/ && cp dist/port-*.* dist/electron/ && cp -R dist/core dist/electron/",
|
|
68
|
+
"copy:api": "mkdir -p dist/api && cp -r ../api/dist/* dist/api/ && cp ../api/package.json dist/api/",
|
|
69
|
+
"copy:core": "mkdir -p dist/core && cp -r ../core/dist/* dist/core/",
|
|
70
|
+
"copy:prxi": "cp src/prxi.tsx dist/prxi.tsx",
|
|
71
|
+
"build:all": "pnpm run build && pnpm run copy:core && pnpm run build:electron && pnpm run copy:electron && pnpm run copy:api && pnpm run copy:prxi",
|
|
72
|
+
"clean": "rm -rf dist",
|
|
73
|
+
"test": "jest",
|
|
74
|
+
"test:watch": "jest --watch",
|
|
75
|
+
"test:coverage": "jest --coverage"
|
|
76
|
+
}
|
|
77
|
+
}
|