pnpm-dash 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.js +1 -1
- package/dist/constants.js +1 -0
- package/dist/ringbuf.js +34 -0
- package/dist/runner.js +3 -1
- package/dist/ui/dashboard.js +20 -3
- package/dist/ui/logview.js +13 -1
- package/dist/ui/statusbar.js +3 -2
- package/package.json +2 -2
package/README.md
CHANGED
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ export function parseCLI() {
|
|
|
4
4
|
program
|
|
5
5
|
.name('pnpm-dash')
|
|
6
6
|
.description('A TUI dashboard for pnpm workspaces - run scripts across packages with a split-pane interface')
|
|
7
|
-
.version('0.1.
|
|
7
|
+
.version('0.1.2')
|
|
8
8
|
.argument('<script>', 'Script name to run across workspace packages (e.g., dev, start)')
|
|
9
9
|
.option('-F, --filter <pattern...>', 'Filter packages by name pattern, supports * for wildcard and ! for exclusions')
|
|
10
10
|
.parse();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const MAX_LOG_LINES = 10000;
|
package/dist/ringbuf.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class RingBuffer {
|
|
2
|
+
buffer;
|
|
3
|
+
head = 0;
|
|
4
|
+
size = 0;
|
|
5
|
+
cap;
|
|
6
|
+
constructor(capacity) {
|
|
7
|
+
this.cap = capacity;
|
|
8
|
+
this.buffer = new Array(capacity);
|
|
9
|
+
}
|
|
10
|
+
push(item) {
|
|
11
|
+
const index = (this.head + this.size) % this.cap;
|
|
12
|
+
if (this.size < this.cap) {
|
|
13
|
+
this.size++;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
this.head = (this.head + 1) % this.cap;
|
|
17
|
+
}
|
|
18
|
+
this.buffer[index] = item;
|
|
19
|
+
}
|
|
20
|
+
clear() {
|
|
21
|
+
this.head = 0;
|
|
22
|
+
this.size = 0;
|
|
23
|
+
}
|
|
24
|
+
toArray() {
|
|
25
|
+
const result = new Array(this.size);
|
|
26
|
+
for (let i = 0; i < this.size; i++) {
|
|
27
|
+
result[i] = this.buffer[(this.head + i) % this.cap];
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
get length() {
|
|
32
|
+
return this.size;
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/runner.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { execa } from 'execa';
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
|
+
import { RingBuffer } from './ringbuf.js';
|
|
4
|
+
import { MAX_LOG_LINES } from './constants.js';
|
|
3
5
|
export class Runner extends EventEmitter {
|
|
4
6
|
states = new Map();
|
|
5
7
|
scriptName;
|
|
@@ -29,7 +31,7 @@ export class Runner extends EventEmitter {
|
|
|
29
31
|
package: pkg,
|
|
30
32
|
status: 'running',
|
|
31
33
|
subprocess: null,
|
|
32
|
-
logs:
|
|
34
|
+
logs: new RingBuffer(MAX_LOG_LINES),
|
|
33
35
|
};
|
|
34
36
|
this.states.set(pkg.name, state);
|
|
35
37
|
}
|
package/dist/ui/dashboard.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import blessed from 'reblessed';
|
|
2
2
|
import { createSidebar, updateSidebarItems } from './sidebar.js';
|
|
3
|
-
import { createLogView, updateLogView, appendLog, toggleLogAutoScroll } from './logview.js';
|
|
3
|
+
import { createLogView, updateLogView, appendLog, toggleLogAutoScroll, expandLogView, shrinkLogView } from './logview.js';
|
|
4
4
|
import { createStatusBar, updateStatusBar } from './statusbar.js';
|
|
5
5
|
export class Dashboard {
|
|
6
6
|
screen;
|
|
@@ -17,6 +17,7 @@ export class Dashboard {
|
|
|
17
17
|
packages: runner.getStates(),
|
|
18
18
|
selectedIndex: 0,
|
|
19
19
|
autoScroll: true,
|
|
20
|
+
sidebarHidden: false,
|
|
20
21
|
};
|
|
21
22
|
this.screen = blessed.screen({
|
|
22
23
|
smartCSR: true,
|
|
@@ -54,6 +55,9 @@ export class Dashboard {
|
|
|
54
55
|
this.screen.key(['c'], () => {
|
|
55
56
|
this.clearSelected();
|
|
56
57
|
});
|
|
58
|
+
this.screen.key(['tab'], () => {
|
|
59
|
+
this.toggleSidebar();
|
|
60
|
+
});
|
|
57
61
|
}
|
|
58
62
|
setupRunnerEvents() {
|
|
59
63
|
this.runner.on('start', (packageName) => {
|
|
@@ -102,7 +106,7 @@ export class Dashboard {
|
|
|
102
106
|
clearSelected() {
|
|
103
107
|
const state = this.getSelectedState();
|
|
104
108
|
if (state) {
|
|
105
|
-
state.logs
|
|
109
|
+
state.logs.clear();
|
|
106
110
|
this.refreshLogView();
|
|
107
111
|
}
|
|
108
112
|
}
|
|
@@ -127,6 +131,19 @@ export class Dashboard {
|
|
|
127
131
|
updateStatusBar(this.statusBar, this.state.autoScroll);
|
|
128
132
|
this.screen.render();
|
|
129
133
|
}
|
|
134
|
+
toggleSidebar() {
|
|
135
|
+
this.state.sidebarHidden = !this.state.sidebarHidden;
|
|
136
|
+
if (this.state.sidebarHidden) {
|
|
137
|
+
this.sidebar.hide();
|
|
138
|
+
expandLogView(this.logView);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
this.sidebar.show();
|
|
142
|
+
shrinkLogView(this.logView);
|
|
143
|
+
}
|
|
144
|
+
updateStatusBar(this.statusBar, this.state.autoScroll);
|
|
145
|
+
this.screen.render();
|
|
146
|
+
}
|
|
130
147
|
refreshSidebar() {
|
|
131
148
|
updateSidebarItems(this.sidebar, this.state.packages, this.state.selectedIndex);
|
|
132
149
|
}
|
|
@@ -141,7 +158,7 @@ export class Dashboard {
|
|
|
141
158
|
start() {
|
|
142
159
|
this.refreshSidebar();
|
|
143
160
|
this.refreshLogView();
|
|
144
|
-
this.
|
|
161
|
+
this.logView.focus();
|
|
145
162
|
this.screen.render();
|
|
146
163
|
}
|
|
147
164
|
}
|
package/dist/ui/logview.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import blessed from 'reblessed';
|
|
2
|
+
import { MAX_LOG_LINES } from '../constants.js';
|
|
2
3
|
export function createLogView(screen, autoScroll) {
|
|
3
4
|
const logView = blessed.log({
|
|
4
5
|
parent: screen,
|
|
@@ -22,6 +23,7 @@ export function createLogView(screen, autoScroll) {
|
|
|
22
23
|
scrollbar: {
|
|
23
24
|
ch: '│',
|
|
24
25
|
},
|
|
26
|
+
scrollback: MAX_LOG_LINES,
|
|
25
27
|
scrollOnInput: autoScroll,
|
|
26
28
|
});
|
|
27
29
|
return logView;
|
|
@@ -34,7 +36,7 @@ export function updateLogView(logView, state) {
|
|
|
34
36
|
return;
|
|
35
37
|
}
|
|
36
38
|
logView.setLabel(` Logs - ${state.package.name} `);
|
|
37
|
-
logView.setContent(state.logs.join('\n'));
|
|
39
|
+
logView.setContent(state.logs.toArray().join('\n'));
|
|
38
40
|
logView.setScroll(0);
|
|
39
41
|
}
|
|
40
42
|
export function appendLog(logView, currentPackage, packageName, line) {
|
|
@@ -49,3 +51,13 @@ export function toggleLogAutoScroll(logView, autoScroll) {
|
|
|
49
51
|
logView.setScrollPerc(100);
|
|
50
52
|
}
|
|
51
53
|
}
|
|
54
|
+
export function expandLogView(logView) {
|
|
55
|
+
logView.left = 0;
|
|
56
|
+
logView.width = '100%';
|
|
57
|
+
logView.border = { type: 'line', top: true, left: false, right: false, bottom: false };
|
|
58
|
+
}
|
|
59
|
+
export function shrinkLogView(logView) {
|
|
60
|
+
logView.left = '25%';
|
|
61
|
+
logView.width = '75%';
|
|
62
|
+
logView.border = { type: 'line', top: true, left: true, right: true, bottom: true };
|
|
63
|
+
}
|
package/dist/ui/statusbar.js
CHANGED
|
@@ -17,7 +17,8 @@ export function createStatusBar(screen) {
|
|
|
17
17
|
}
|
|
18
18
|
export function updateStatusBar(statusBar, autoScroll) {
|
|
19
19
|
const scrollStatus = autoScroll ? 'ON' : 'OFF';
|
|
20
|
-
statusBar.setContent(` {bold}Q{/bold}:exit {bold}
|
|
20
|
+
statusBar.setContent(` {bold}Q{/bold}:exit {bold}tab{/bold}:toggle sidebar ` +
|
|
21
|
+
` {bold}q{/bold}:quit task {bold}r{/bold}:restart task ` +
|
|
21
22
|
` {bold}R{/bold}:restart all {bold}j/k{/bold}:navigate {bold}c{/bold}:clear ` +
|
|
22
|
-
` {bold}s{/bold}:autoscroll [${scrollStatus}]`);
|
|
23
|
+
` {bold}s{/bold}:autoscroll [${scrollStatus}] `);
|
|
23
24
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pnpm-dash",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "A TUI dashboard for pnpm workspaces - run scripts across packages with a split-pane interface",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"terminal"
|
|
25
25
|
],
|
|
26
26
|
"author": "artygus",
|
|
27
|
-
"license": "
|
|
27
|
+
"license": "Unlicense",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@pnpm/find-workspace-dir": "^7.0.2",
|
|
30
30
|
"@pnpm/workspace.find-packages": "^4.0.5",
|