spawn-term 1.1.8 → 2.1.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.
Files changed (73) hide show
  1. package/dist/cjs/components/App.js +159 -9
  2. package/dist/cjs/components/App.js.map +1 -1
  3. package/dist/cjs/components/CompactProcessLine.js +162 -0
  4. package/dist/cjs/components/CompactProcessLine.js.map +1 -0
  5. package/dist/cjs/components/Divider.js +24 -0
  6. package/dist/cjs/components/Divider.js.map +1 -0
  7. package/dist/cjs/components/ErrorDetailModal.js +115 -0
  8. package/dist/cjs/components/ErrorDetailModal.js.map +1 -0
  9. package/dist/cjs/components/ErrorListModal.js +135 -0
  10. package/dist/cjs/components/ErrorListModal.js.map +1 -0
  11. package/dist/cjs/components/ExpandedOutput.js +55 -0
  12. package/dist/cjs/components/ExpandedOutput.js.map +1 -0
  13. package/dist/cjs/components/StatusBar.js +104 -0
  14. package/dist/cjs/components/StatusBar.js.map +1 -0
  15. package/dist/cjs/constants.js +42 -0
  16. package/dist/cjs/constants.js.map +1 -0
  17. package/dist/cjs/createApp.js +7 -2
  18. package/dist/cjs/createApp.js.map +1 -1
  19. package/dist/cjs/lib/addLines.js +58 -4
  20. package/dist/cjs/lib/addLines.js.map +1 -1
  21. package/dist/cjs/lib/format.js +21 -0
  22. package/dist/cjs/lib/format.js.map +1 -0
  23. package/dist/cjs/src/components/CompactProcessLine.d.ts +7 -0
  24. package/dist/cjs/src/components/Divider.d.ts +2 -0
  25. package/dist/cjs/src/components/ErrorDetailModal.d.ts +8 -0
  26. package/dist/cjs/src/components/ErrorListModal.d.ts +8 -0
  27. package/dist/cjs/src/components/ExpandedOutput.d.ts +8 -0
  28. package/dist/cjs/src/components/StatusBar.d.ts +8 -0
  29. package/dist/cjs/src/constants.d.ts +7 -0
  30. package/dist/cjs/src/lib/addLines.d.ts +6 -1
  31. package/dist/cjs/src/lib/format.d.ts +2 -0
  32. package/dist/cjs/src/state/processStore.d.ts +36 -0
  33. package/dist/cjs/src/types.d.ts +6 -0
  34. package/dist/cjs/state/processStore.js +202 -0
  35. package/dist/cjs/state/processStore.js.map +1 -1
  36. package/dist/cjs/types.js.map +1 -1
  37. package/dist/esm/components/App.js +159 -9
  38. package/dist/esm/components/App.js.map +1 -1
  39. package/dist/esm/components/CompactProcessLine.js +143 -0
  40. package/dist/esm/components/CompactProcessLine.js.map +1 -0
  41. package/dist/esm/components/Divider.js +13 -0
  42. package/dist/esm/components/Divider.js.map +1 -0
  43. package/dist/esm/components/ErrorDetailModal.js +99 -0
  44. package/dist/esm/components/ErrorDetailModal.js.map +1 -0
  45. package/dist/esm/components/ErrorListModal.js +116 -0
  46. package/dist/esm/components/ErrorListModal.js.map +1 -0
  47. package/dist/esm/components/ExpandedOutput.js +41 -0
  48. package/dist/esm/components/ExpandedOutput.js.map +1 -0
  49. package/dist/esm/components/StatusBar.js +87 -0
  50. package/dist/esm/components/StatusBar.js.map +1 -0
  51. package/dist/esm/constants.js +11 -0
  52. package/dist/esm/constants.js.map +1 -0
  53. package/dist/esm/createApp.js +7 -2
  54. package/dist/esm/createApp.js.map +1 -1
  55. package/dist/esm/lib/addLines.js +32 -5
  56. package/dist/esm/lib/addLines.js.map +1 -1
  57. package/dist/esm/lib/format.js +10 -0
  58. package/dist/esm/lib/format.js.map +1 -0
  59. package/dist/esm/src/components/CompactProcessLine.d.ts +7 -0
  60. package/dist/esm/src/components/Divider.d.ts +2 -0
  61. package/dist/esm/src/components/ErrorDetailModal.d.ts +8 -0
  62. package/dist/esm/src/components/ErrorListModal.d.ts +8 -0
  63. package/dist/esm/src/components/ExpandedOutput.d.ts +8 -0
  64. package/dist/esm/src/components/StatusBar.d.ts +8 -0
  65. package/dist/esm/src/constants.d.ts +7 -0
  66. package/dist/esm/src/lib/addLines.d.ts +6 -1
  67. package/dist/esm/src/lib/format.d.ts +2 -0
  68. package/dist/esm/src/state/processStore.d.ts +36 -0
  69. package/dist/esm/src/types.d.ts +6 -0
  70. package/dist/esm/state/processStore.js +146 -0
  71. package/dist/esm/state/processStore.js.map +1 -1
  72. package/dist/esm/types.js.map +1 -1
  73. package/package.json +1 -1
@@ -1,20 +1,47 @@
1
1
  import { Writable } from 'stream';
2
+ import { BATCH_MAX_LINES, BATCH_MAX_WAIT_MS } from '../constants.js';
2
3
  const REGEX_NEW_LINE = /\r?\n|\r/g;
3
- export default function addLines(fn) {
4
+ export default function addLines(fn, options = {}) {
5
+ const { maxLines = BATCH_MAX_LINES, maxWait = BATCH_MAX_WAIT_MS } = options;
4
6
  let last = '';
7
+ let lineBuffer = [];
8
+ let flushTimer = null;
9
+ const flush = ()=>{
10
+ if (flushTimer) {
11
+ clearTimeout(flushTimer);
12
+ flushTimer = null;
13
+ }
14
+ if (lineBuffer.length > 0) {
15
+ fn(lineBuffer);
16
+ lineBuffer = [];
17
+ }
18
+ };
19
+ const scheduleFlush = ()=>{
20
+ if (!flushTimer) {
21
+ flushTimer = setTimeout(flush, maxWait);
22
+ }
23
+ };
5
24
  const stream = new Writable({
6
25
  write (chunk, _enc, callback) {
7
26
  const more = last + chunk.toString('utf8');
8
27
  const lines = more.split(REGEX_NEW_LINE);
9
28
  last = lines.pop();
10
- if (lines.length > 0) fn(lines);
29
+ if (lines.length > 0) {
30
+ lineBuffer.push(...lines);
31
+ // Flush immediately if buffer is large enough
32
+ if (lineBuffer.length >= maxLines) {
33
+ flush();
34
+ } else {
35
+ scheduleFlush();
36
+ }
37
+ }
11
38
  callback();
12
39
  }
13
40
  });
14
41
  stream.on('finish', ()=>{
15
- if (last.length) fn([
16
- last
17
- ]);
42
+ // Flush any remaining buffered lines
43
+ if (last.length) lineBuffer.push(last);
44
+ flush();
18
45
  last = '';
19
46
  });
20
47
  return stream;
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/addLines.ts"],"sourcesContent":["import { Writable } from 'stream';\n\nconst REGEX_NEW_LINE = /\\r?\\n|\\r/g;\n\nexport type Callback = (lines: string[]) => undefined;\n\nexport default function addLines(fn: Callback): Writable {\n let last = '';\n\n const stream = new Writable({\n write(chunk, _enc, callback) {\n const more = last + chunk.toString('utf8');\n const lines = more.split(REGEX_NEW_LINE);\n last = lines.pop();\n if (lines.length > 0) fn(lines);\n callback();\n },\n });\n stream.on('finish', () => {\n if (last.length) fn([last]);\n last = '';\n });\n return stream;\n}\n"],"names":["Writable","REGEX_NEW_LINE","addLines","fn","last","stream","write","chunk","_enc","callback","more","toString","lines","split","pop","length","on"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,SAAS;AAElC,MAAMC,iBAAiB;AAIvB,eAAe,SAASC,SAASC,EAAY;IAC3C,IAAIC,OAAO;IAEX,MAAMC,SAAS,IAAIL,SAAS;QAC1BM,OAAMC,KAAK,EAAEC,IAAI,EAAEC,QAAQ;YACzB,MAAMC,OAAON,OAAOG,MAAMI,QAAQ,CAAC;YACnC,MAAMC,QAAQF,KAAKG,KAAK,CAACZ;YACzBG,OAAOQ,MAAME,GAAG;YAChB,IAAIF,MAAMG,MAAM,GAAG,GAAGZ,GAAGS;YACzBH;QACF;IACF;IACAJ,OAAOW,EAAE,CAAC,UAAU;QAClB,IAAIZ,KAAKW,MAAM,EAAEZ,GAAG;YAACC;SAAK;QAC1BA,OAAO;IACT;IACA,OAAOC;AACT"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/addLines.ts"],"sourcesContent":["import { Writable } from 'stream';\nimport { BATCH_MAX_LINES, BATCH_MAX_WAIT_MS } from '../constants.ts';\n\nconst REGEX_NEW_LINE = /\\r?\\n|\\r/g;\n\nexport type Callback = (lines: string[]) => undefined;\n\ninterface BatchOptions {\n maxLines?: number;\n maxWait?: number;\n}\n\nexport default function addLines(fn: Callback, options: BatchOptions = {}): Writable {\n const { maxLines = BATCH_MAX_LINES, maxWait = BATCH_MAX_WAIT_MS } = options;\n\n let last = '';\n let lineBuffer: string[] = [];\n let flushTimer: NodeJS.Timeout | null = null;\n\n const flush = () => {\n if (flushTimer) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n if (lineBuffer.length > 0) {\n fn(lineBuffer);\n lineBuffer = [];\n }\n };\n\n const scheduleFlush = () => {\n if (!flushTimer) {\n flushTimer = setTimeout(flush, maxWait);\n }\n };\n\n const stream = new Writable({\n write(chunk, _enc, callback) {\n const more = last + chunk.toString('utf8');\n const lines = more.split(REGEX_NEW_LINE);\n last = lines.pop();\n\n if (lines.length > 0) {\n lineBuffer.push(...lines);\n\n // Flush immediately if buffer is large enough\n if (lineBuffer.length >= maxLines) {\n flush();\n } else {\n scheduleFlush();\n }\n }\n callback();\n },\n });\n\n stream.on('finish', () => {\n // Flush any remaining buffered lines\n if (last.length) lineBuffer.push(last);\n flush();\n last = '';\n });\n\n return stream;\n}\n"],"names":["Writable","BATCH_MAX_LINES","BATCH_MAX_WAIT_MS","REGEX_NEW_LINE","addLines","fn","options","maxLines","maxWait","last","lineBuffer","flushTimer","flush","clearTimeout","length","scheduleFlush","setTimeout","stream","write","chunk","_enc","callback","more","toString","lines","split","pop","push","on"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,SAAS;AAClC,SAASC,eAAe,EAAEC,iBAAiB,QAAQ,kBAAkB;AAErE,MAAMC,iBAAiB;AASvB,eAAe,SAASC,SAASC,EAAY,EAAEC,UAAwB,CAAC,CAAC;IACvE,MAAM,EAAEC,WAAWN,eAAe,EAAEO,UAAUN,iBAAiB,EAAE,GAAGI;IAEpE,IAAIG,OAAO;IACX,IAAIC,aAAuB,EAAE;IAC7B,IAAIC,aAAoC;IAExC,MAAMC,QAAQ;QACZ,IAAID,YAAY;YACdE,aAAaF;YACbA,aAAa;QACf;QACA,IAAID,WAAWI,MAAM,GAAG,GAAG;YACzBT,GAAGK;YACHA,aAAa,EAAE;QACjB;IACF;IAEA,MAAMK,gBAAgB;QACpB,IAAI,CAACJ,YAAY;YACfA,aAAaK,WAAWJ,OAAOJ;QACjC;IACF;IAEA,MAAMS,SAAS,IAAIjB,SAAS;QAC1BkB,OAAMC,KAAK,EAAEC,IAAI,EAAEC,QAAQ;YACzB,MAAMC,OAAOb,OAAOU,MAAMI,QAAQ,CAAC;YACnC,MAAMC,QAAQF,KAAKG,KAAK,CAACtB;YACzBM,OAAOe,MAAME,GAAG;YAEhB,IAAIF,MAAMV,MAAM,GAAG,GAAG;gBACpBJ,WAAWiB,IAAI,IAAIH;gBAEnB,8CAA8C;gBAC9C,IAAId,WAAWI,MAAM,IAAIP,UAAU;oBACjCK;gBACF,OAAO;oBACLG;gBACF;YACF;YACAM;QACF;IACF;IAEAJ,OAAOW,EAAE,CAAC,UAAU;QAClB,qCAAqC;QACrC,IAAInB,KAAKK,MAAM,EAAEJ,WAAWiB,IAAI,CAAClB;QACjCG;QACAH,OAAO;IACT;IAEA,OAAOQ;AACT"}
@@ -0,0 +1,10 @@
1
+ import { FALLBACK_COLUMN_WIDTH, MAX_COLUMN_WIDTH_PERCENT } from '../constants.js';
2
+ export function calculateColumnWidth(groupWidth, terminalWidth, maxGroupLength) {
3
+ if (typeof groupWidth === 'number') return groupWidth;
4
+ if (groupWidth === 'max') return Math.min(maxGroupLength, Math.floor(terminalWidth * MAX_COLUMN_WIDTH_PERCENT));
5
+ if (typeof groupWidth === 'string' && groupWidth.endsWith('%')) {
6
+ const pct = parseInt(groupWidth, 10) / 100;
7
+ return Math.floor(terminalWidth * pct);
8
+ }
9
+ return FALLBACK_COLUMN_WIDTH;
10
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/format.ts"],"sourcesContent":["import { FALLBACK_COLUMN_WIDTH, MAX_COLUMN_WIDTH_PERCENT } from '../constants.ts';\n\nexport type GroupWidth = number | `${number}%` | 'max';\n\nexport function calculateColumnWidth(groupWidth: GroupWidth, terminalWidth: number, maxGroupLength: number): number {\n if (typeof groupWidth === 'number') return groupWidth;\n if (groupWidth === 'max') return Math.min(maxGroupLength, Math.floor(terminalWidth * MAX_COLUMN_WIDTH_PERCENT));\n if (typeof groupWidth === 'string' && groupWidth.endsWith('%')) {\n const pct = parseInt(groupWidth, 10) / 100;\n return Math.floor(terminalWidth * pct);\n }\n return FALLBACK_COLUMN_WIDTH;\n}\n"],"names":["FALLBACK_COLUMN_WIDTH","MAX_COLUMN_WIDTH_PERCENT","calculateColumnWidth","groupWidth","terminalWidth","maxGroupLength","Math","min","floor","endsWith","pct","parseInt"],"mappings":"AAAA,SAASA,qBAAqB,EAAEC,wBAAwB,QAAQ,kBAAkB;AAIlF,OAAO,SAASC,qBAAqBC,UAAsB,EAAEC,aAAqB,EAAEC,cAAsB;IACxG,IAAI,OAAOF,eAAe,UAAU,OAAOA;IAC3C,IAAIA,eAAe,OAAO,OAAOG,KAAKC,GAAG,CAACF,gBAAgBC,KAAKE,KAAK,CAACJ,gBAAgBH;IACrF,IAAI,OAAOE,eAAe,YAAYA,WAAWM,QAAQ,CAAC,MAAM;QAC9D,MAAMC,MAAMC,SAASR,YAAY,MAAM;QACvC,OAAOG,KAAKE,KAAK,CAACJ,gBAAgBM;IACpC;IACA,OAAOV;AACT"}
@@ -0,0 +1,7 @@
1
+ import type { ChildProcess } from '../types.js';
2
+ type Props = {
3
+ item: ChildProcess;
4
+ isSelected?: boolean;
5
+ };
6
+ declare const _default: import("react").NamedExoticComponent<Props>;
7
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("react").NamedExoticComponent<object>;
2
+ export default _default;
@@ -0,0 +1,8 @@
1
+ import type { ChildProcess } from '../types.js';
2
+ type Props = {
3
+ error: ChildProcess;
4
+ currentIndex: number;
5
+ totalErrors: number;
6
+ };
7
+ declare const _default: import("react").NamedExoticComponent<Props>;
8
+ export default _default;
@@ -0,0 +1,8 @@
1
+ import type { ChildProcess } from '../types.js';
2
+ type Props = {
3
+ errors: ChildProcess[];
4
+ selectedIndex: number;
5
+ totalErrorLines: number;
6
+ };
7
+ declare const _default: import("react").NamedExoticComponent<Props>;
8
+ export default _default;
@@ -0,0 +1,8 @@
1
+ import type { Line } from '../types.js';
2
+ type Props = {
3
+ lines: Line[];
4
+ scrollOffset: number;
5
+ maxVisible?: number;
6
+ };
7
+ declare const _default: import("react").NamedExoticComponent<Props>;
8
+ export default _default;
@@ -0,0 +1,8 @@
1
+ type Props = {
2
+ running: number;
3
+ done: number;
4
+ errors: number;
5
+ errorLines: number;
6
+ };
7
+ declare const _default: import("react").NamedExoticComponent<Props>;
8
+ export default _default;
@@ -0,0 +1,7 @@
1
+ export declare const DEFAULT_COLUMN_WIDTH = 15;
2
+ export declare const MAX_COLUMN_WIDTH_PERCENT = 0.4;
3
+ export declare const FALLBACK_COLUMN_WIDTH = 25;
4
+ export declare const BATCH_MAX_LINES = 20;
5
+ export declare const BATCH_MAX_WAIT_MS = 50;
6
+ export declare const DEFAULT_MAX_FPS = 20;
7
+ export declare const EXPANDED_MAX_VISIBLE_LINES = 10;
@@ -1,3 +1,8 @@
1
1
  import { Writable } from 'stream';
2
2
  export type Callback = (lines: string[]) => undefined;
3
- export default function addLines(fn: Callback): Writable;
3
+ interface BatchOptions {
4
+ maxLines?: number;
5
+ maxWait?: number;
6
+ }
7
+ export default function addLines(fn: Callback, options?: BatchOptions): Writable;
8
+ export {};
@@ -0,0 +1,2 @@
1
+ export type GroupWidth = number | `${number}%` | 'max';
2
+ export declare function calculateColumnWidth(groupWidth: GroupWidth, terminalWidth: number, maxGroupLength: number): number;
@@ -1,16 +1,52 @@
1
1
  import type { ChildProcess, Line } from '../types.js';
2
2
  type Listener = () => void;
3
+ type Mode = 'normal' | 'interactive' | 'errorList' | 'errorDetail';
3
4
  declare class ProcessStore {
4
5
  private processes;
6
+ private completedIds;
5
7
  private listeners;
6
8
  private shouldExit;
7
9
  private exitCallback;
10
+ private mode;
11
+ private selectedIndex;
12
+ private selectedErrorIndex;
13
+ private expandedId;
14
+ private scrollOffset;
15
+ private header;
8
16
  subscribe: (listener: Listener) => (() => void);
9
17
  getSnapshot: () => ChildProcess[];
18
+ getRunningProcesses: () => ChildProcess[];
19
+ getCompletedProcesses: () => ChildProcess[];
20
+ getFailedProcesses: () => ChildProcess[];
21
+ getRunningCount: () => number;
22
+ getMaxGroupLength: () => number;
23
+ getDoneCount: () => number;
24
+ getErrorCount: () => number;
25
+ getErrorLineCount: () => number;
26
+ getMode: () => Mode;
27
+ getSelectedIndex: () => number;
28
+ getSelectedErrorIndex: () => number;
29
+ getExpandedId: () => string | null;
30
+ getScrollOffset: () => number;
31
+ getHeader: () => string | undefined;
32
+ getShowStatusBar: () => boolean;
33
+ getIsInteractive: () => boolean;
34
+ isAllComplete: () => boolean;
10
35
  addProcess(process: ChildProcess): void;
11
36
  updateProcess(id: string, update: Partial<ChildProcess>): void;
12
37
  appendLines(id: string, newLines: Line[]): void;
13
38
  getProcess(id: string): ChildProcess | undefined;
39
+ setMode(mode: Mode): void;
40
+ selectNext(): void;
41
+ selectPrev(): void;
42
+ getSelectedProcess(): ChildProcess | undefined;
43
+ selectNextError(): void;
44
+ selectPrevError(): void;
45
+ getSelectedError(): ChildProcess | undefined;
46
+ toggleExpand(): void;
47
+ collapse(): void;
48
+ scrollDown(maxVisible: number): void;
49
+ scrollUp(): void;
14
50
  signalExit(callback: () => void): void;
15
51
  getShouldExit: () => boolean;
16
52
  getExitCallback: () => (() => void) | null;
@@ -3,6 +3,9 @@ import type { SpawnError, SpawnResult } from 'cross-spawn-cb';
3
3
  export type TerminalOptions = {
4
4
  group?: string;
5
5
  expanded?: boolean;
6
+ header?: string;
7
+ showStatusBar?: boolean;
8
+ interactive?: boolean;
6
9
  };
7
10
  export type TerminalCallback = (error?: SpawnError, result?: SpawnResult) => undefined;
8
11
  export declare const LineType: {
@@ -21,4 +24,7 @@ export type ChildProcess = {
21
24
  state: State;
22
25
  lines: Line[];
23
26
  expanded?: boolean;
27
+ header?: string;
28
+ showStatusBar?: boolean;
29
+ interactive?: boolean;
24
30
  };
@@ -26,9 +26,15 @@ function _object_spread(target) {
26
26
  }
27
27
  return target;
28
28
  }
29
+ import { DEFAULT_COLUMN_WIDTH } from '../constants.js';
30
+ import { LineType } from '../types.js';
29
31
  class ProcessStore {
30
32
  // Mutations - Ink handles render throttling at 30 FPS
31
33
  addProcess(process) {
34
+ // Set header on first process that provides one
35
+ if (this.header === undefined && process.header !== undefined) {
36
+ this.header = process.header;
37
+ }
32
38
  this.processes = [
33
39
  ...this.processes,
34
40
  process
@@ -36,7 +42,17 @@ class ProcessStore {
36
42
  this.notify();
37
43
  }
38
44
  updateProcess(id, update) {
45
+ const oldProcess = this.processes.find((p)=>p.id === id);
46
+ const wasRunning = (oldProcess === null || oldProcess === void 0 ? void 0 : oldProcess.state) === 'running';
47
+ const isNowComplete = update.state && update.state !== 'running';
39
48
  this.processes = this.processes.map((p)=>p.id === id ? _object_spread({}, p, update) : p);
49
+ // Track completion order
50
+ if (wasRunning && isNowComplete && !this.completedIds.includes(id)) {
51
+ this.completedIds = [
52
+ ...this.completedIds,
53
+ id
54
+ ];
55
+ }
40
56
  this.notify();
41
57
  }
42
58
  appendLines(id, newLines) {
@@ -50,6 +66,87 @@ class ProcessStore {
50
66
  getProcess(id) {
51
67
  return this.processes.find((p)=>p.id === id);
52
68
  }
69
+ // UI state mutations
70
+ setMode(mode) {
71
+ this.mode = mode;
72
+ if (mode === 'interactive') {
73
+ this.selectedIndex = 0;
74
+ } else if (mode === 'errorList') {
75
+ this.selectedErrorIndex = 0;
76
+ }
77
+ this.notify();
78
+ }
79
+ // Interactive mode navigation
80
+ selectNext() {
81
+ if (this.processes.length > 0) {
82
+ this.selectedIndex = (this.selectedIndex + 1) % this.processes.length;
83
+ this.notify();
84
+ }
85
+ }
86
+ selectPrev() {
87
+ if (this.processes.length > 0) {
88
+ this.selectedIndex = (this.selectedIndex - 1 + this.processes.length) % this.processes.length;
89
+ this.notify();
90
+ }
91
+ }
92
+ getSelectedProcess() {
93
+ return this.processes[this.selectedIndex];
94
+ }
95
+ selectNextError() {
96
+ const failed = this.getFailedProcesses();
97
+ if (failed.length > 0) {
98
+ this.selectedErrorIndex = (this.selectedErrorIndex + 1) % failed.length;
99
+ this.notify();
100
+ }
101
+ }
102
+ selectPrevError() {
103
+ const failed = this.getFailedProcesses();
104
+ if (failed.length > 0) {
105
+ this.selectedErrorIndex = (this.selectedErrorIndex - 1 + failed.length) % failed.length;
106
+ this.notify();
107
+ }
108
+ }
109
+ getSelectedError() {
110
+ const failed = this.getFailedProcesses();
111
+ return failed[this.selectedErrorIndex];
112
+ }
113
+ // Expansion methods
114
+ toggleExpand() {
115
+ const selected = this.getSelectedProcess();
116
+ if (!selected) return;
117
+ if (this.expandedId === selected.id) {
118
+ // Collapse
119
+ this.expandedId = null;
120
+ this.scrollOffset = 0;
121
+ } else {
122
+ // Expand
123
+ this.expandedId = selected.id;
124
+ this.scrollOffset = 0;
125
+ }
126
+ this.notify();
127
+ }
128
+ collapse() {
129
+ this.expandedId = null;
130
+ this.scrollOffset = 0;
131
+ this.notify();
132
+ }
133
+ scrollDown(maxVisible) {
134
+ if (!this.expandedId) return;
135
+ const process = this.getProcess(this.expandedId);
136
+ if (!process) return;
137
+ const maxOffset = Math.max(0, process.lines.length - maxVisible);
138
+ if (this.scrollOffset < maxOffset) {
139
+ this.scrollOffset++;
140
+ this.notify();
141
+ }
142
+ }
143
+ scrollUp() {
144
+ if (!this.expandedId) return;
145
+ if (this.scrollOffset > 0) {
146
+ this.scrollOffset--;
147
+ this.notify();
148
+ }
149
+ }
53
150
  // Exit signaling
54
151
  signalExit(callback) {
55
152
  this.shouldExit = true;
@@ -58,8 +155,15 @@ class ProcessStore {
58
155
  }
59
156
  reset() {
60
157
  this.processes = [];
158
+ this.completedIds = [];
61
159
  this.shouldExit = false;
62
160
  this.exitCallback = null;
161
+ this.mode = 'normal';
162
+ this.selectedIndex = 0;
163
+ this.selectedErrorIndex = 0;
164
+ this.expandedId = null;
165
+ this.scrollOffset = 0;
166
+ this.header = undefined;
63
167
  }
64
168
  notify() {
65
169
  this.listeners.forEach((l)=>{
@@ -68,15 +172,57 @@ class ProcessStore {
68
172
  }
69
173
  constructor(){
70
174
  this.processes = [];
175
+ this.completedIds = []; // Track completion order
71
176
  this.listeners = new Set();
72
177
  this.shouldExit = false;
73
178
  this.exitCallback = null;
179
+ // UI state
180
+ this.mode = 'normal';
181
+ this.selectedIndex = 0;
182
+ this.selectedErrorIndex = 0;
183
+ this.expandedId = null;
184
+ this.scrollOffset = 0;
74
185
  // useSyncExternalStore API
75
186
  this.subscribe = (listener)=>{
76
187
  this.listeners.add(listener);
77
188
  return ()=>this.listeners.delete(listener);
78
189
  };
79
190
  this.getSnapshot = ()=>this.processes;
191
+ // Filtered getters
192
+ this.getRunningProcesses = ()=>{
193
+ return this.processes.filter((p)=>p.state === 'running');
194
+ };
195
+ this.getCompletedProcesses = ()=>{
196
+ // Return in completion order
197
+ return this.completedIds.map((id)=>this.processes.find((p)=>p.id === id)).filter((p)=>p !== undefined);
198
+ };
199
+ this.getFailedProcesses = ()=>{
200
+ return this.processes.filter((p)=>p.state === 'error');
201
+ };
202
+ // Counts
203
+ this.getRunningCount = ()=>this.processes.filter((p)=>p.state === 'running').length;
204
+ this.getMaxGroupLength = ()=>{
205
+ if (this.processes.length === 0) return DEFAULT_COLUMN_WIDTH;
206
+ return Math.max(...this.processes.map((p)=>(p.group || p.title).length));
207
+ };
208
+ this.getDoneCount = ()=>this.processes.filter((p)=>p.state !== 'running').length;
209
+ this.getErrorCount = ()=>this.processes.filter((p)=>p.state === 'error').length;
210
+ this.getErrorLineCount = ()=>{
211
+ return this.processes.filter((p)=>p.state === 'error').reduce((total, p)=>total + p.lines.filter((l)=>l.type === LineType.stderr).length, 0);
212
+ };
213
+ // UI state getters
214
+ this.getMode = ()=>this.mode;
215
+ this.getSelectedIndex = ()=>this.selectedIndex;
216
+ this.getSelectedErrorIndex = ()=>this.selectedErrorIndex;
217
+ this.getExpandedId = ()=>this.expandedId;
218
+ this.getScrollOffset = ()=>this.scrollOffset;
219
+ // Get header
220
+ this.getHeader = ()=>this.header;
221
+ // Show status bar only if any process sets showStatusBar: true (default: false)
222
+ this.getShowStatusBar = ()=>this.processes.some((p)=>p.showStatusBar === true);
223
+ // Interactive mode if any process has interactive: true
224
+ this.getIsInteractive = ()=>this.processes.some((p)=>p.interactive === true);
225
+ this.isAllComplete = ()=>this.processes.length > 0 && this.processes.every((p)=>p.state !== 'running');
80
226
  this.getShouldExit = ()=>this.shouldExit;
81
227
  this.getExitCallback = ()=>this.exitCallback;
82
228
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/state/processStore.ts"],"sourcesContent":["import type { ChildProcess, Line } from '../types.ts';\n\ntype Listener = () => void;\n\nclass ProcessStore {\n private processes: ChildProcess[] = [];\n private listeners = new Set<Listener>();\n private shouldExit = false;\n private exitCallback: (() => void) | null = null;\n\n // useSyncExternalStore API\n subscribe = (listener: Listener): (() => void) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n };\n\n getSnapshot = (): ChildProcess[] => this.processes;\n\n // Mutations - Ink handles render throttling at 30 FPS\n addProcess(process: ChildProcess): void {\n this.processes = [...this.processes, process];\n this.notify();\n }\n\n updateProcess(id: string, update: Partial<ChildProcess>): void {\n this.processes = this.processes.map((p) => (p.id === id ? { ...p, ...update } : p));\n this.notify();\n }\n\n appendLines(id: string, newLines: Line[]): void {\n const process = this.processes.find((p) => p.id === id);\n if (process) {\n this.updateProcess(id, { lines: process.lines.concat(newLines) });\n }\n }\n\n getProcess(id: string): ChildProcess | undefined {\n return this.processes.find((p) => p.id === id);\n }\n\n // Exit signaling\n signalExit(callback: () => void): void {\n this.shouldExit = true;\n this.exitCallback = callback;\n this.notify();\n }\n\n getShouldExit = (): boolean => this.shouldExit;\n getExitCallback = (): (() => void) | null => this.exitCallback;\n\n reset(): void {\n this.processes = [];\n this.shouldExit = false;\n this.exitCallback = null;\n }\n\n private notify(): void {\n this.listeners.forEach((l) => {\n l();\n });\n }\n}\n\nexport const processStore = new ProcessStore();\nexport type { ProcessStore };\n"],"names":["ProcessStore","addProcess","process","processes","notify","updateProcess","id","update","map","p","appendLines","newLines","find","lines","concat","getProcess","signalExit","callback","shouldExit","exitCallback","reset","listeners","forEach","l","Set","subscribe","listener","add","delete","getSnapshot","getShouldExit","getExitCallback","processStore"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAMA;IAcJ,sDAAsD;IACtDC,WAAWC,OAAqB,EAAQ;QACtC,IAAI,CAACC,SAAS,GAAG;eAAI,IAAI,CAACA,SAAS;YAAED;SAAQ;QAC7C,IAAI,CAACE,MAAM;IACb;IAEAC,cAAcC,EAAU,EAAEC,MAA6B,EAAQ;QAC7D,IAAI,CAACJ,SAAS,GAAG,IAAI,CAACA,SAAS,CAACK,GAAG,CAAC,CAACC,IAAOA,EAAEH,EAAE,KAAKA,KAAK,mBAAKG,GAAMF,UAAWE;QAChF,IAAI,CAACL,MAAM;IACb;IAEAM,YAAYJ,EAAU,EAAEK,QAAgB,EAAQ;QAC9C,MAAMT,UAAU,IAAI,CAACC,SAAS,CAACS,IAAI,CAAC,CAACH,IAAMA,EAAEH,EAAE,KAAKA;QACpD,IAAIJ,SAAS;YACX,IAAI,CAACG,aAAa,CAACC,IAAI;gBAAEO,OAAOX,QAAQW,KAAK,CAACC,MAAM,CAACH;YAAU;QACjE;IACF;IAEAI,WAAWT,EAAU,EAA4B;QAC/C,OAAO,IAAI,CAACH,SAAS,CAACS,IAAI,CAAC,CAACH,IAAMA,EAAEH,EAAE,KAAKA;IAC7C;IAEA,iBAAiB;IACjBU,WAAWC,QAAoB,EAAQ;QACrC,IAAI,CAACC,UAAU,GAAG;QAClB,IAAI,CAACC,YAAY,GAAGF;QACpB,IAAI,CAACb,MAAM;IACb;IAKAgB,QAAc;QACZ,IAAI,CAACjB,SAAS,GAAG,EAAE;QACnB,IAAI,CAACe,UAAU,GAAG;QAClB,IAAI,CAACC,YAAY,GAAG;IACtB;IAEQf,SAAe;QACrB,IAAI,CAACiB,SAAS,CAACC,OAAO,CAAC,CAACC;YACtBA;QACF;IACF;;aAvDQpB,YAA4B,EAAE;aAC9BkB,YAAY,IAAIG;aAChBN,aAAa;aACbC,eAAoC;QAE5C,2BAA2B;aAC3BM,YAAY,CAACC;YACX,IAAI,CAACL,SAAS,CAACM,GAAG,CAACD;YACnB,OAAO,IAAM,IAAI,CAACL,SAAS,CAACO,MAAM,CAACF;QACrC;aAEAG,cAAc,IAAsB,IAAI,CAAC1B,SAAS;aA+BlD2B,gBAAgB,IAAe,IAAI,CAACZ,UAAU;aAC9Ca,kBAAkB,IAA2B,IAAI,CAACZ,YAAY;;AAahE;AAEA,OAAO,MAAMa,eAAe,IAAIhC,eAAe"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/state/processStore.ts"],"sourcesContent":["import { DEFAULT_COLUMN_WIDTH } from '../constants.ts';\nimport type { ChildProcess, Line } from '../types.ts';\nimport { LineType } from '../types.ts';\n\ntype Listener = () => void;\ntype Mode = 'normal' | 'interactive' | 'errorList' | 'errorDetail';\n\nclass ProcessStore {\n private processes: ChildProcess[] = [];\n private completedIds: string[] = []; // Track completion order\n private listeners = new Set<Listener>();\n private shouldExit = false;\n private exitCallback: (() => void) | null = null;\n\n // UI state\n private mode: Mode = 'normal';\n private selectedIndex = 0;\n private selectedErrorIndex = 0;\n private expandedId: string | null = null;\n private scrollOffset = 0;\n\n // App-level display settings\n private header: string | undefined;\n\n // useSyncExternalStore API\n subscribe = (listener: Listener): (() => void) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n };\n\n getSnapshot = (): ChildProcess[] => this.processes;\n\n // Filtered getters\n getRunningProcesses = (): ChildProcess[] => {\n return this.processes.filter((p) => p.state === 'running');\n };\n\n getCompletedProcesses = (): ChildProcess[] => {\n // Return in completion order\n return this.completedIds.map((id) => this.processes.find((p) => p.id === id)).filter((p): p is ChildProcess => p !== undefined);\n };\n\n getFailedProcesses = (): ChildProcess[] => {\n return this.processes.filter((p) => p.state === 'error');\n };\n\n // Counts\n getRunningCount = (): number => this.processes.filter((p) => p.state === 'running').length;\n getMaxGroupLength = (): number => {\n if (this.processes.length === 0) return DEFAULT_COLUMN_WIDTH;\n return Math.max(...this.processes.map((p) => (p.group || p.title).length));\n };\n getDoneCount = (): number => this.processes.filter((p) => p.state !== 'running').length;\n getErrorCount = (): number => this.processes.filter((p) => p.state === 'error').length;\n getErrorLineCount = (): number => {\n return this.processes.filter((p) => p.state === 'error').reduce((total, p) => total + p.lines.filter((l) => l.type === LineType.stderr).length, 0);\n };\n\n // UI state getters\n getMode = (): Mode => this.mode;\n getSelectedIndex = (): number => this.selectedIndex;\n getSelectedErrorIndex = (): number => this.selectedErrorIndex;\n getExpandedId = (): string | null => this.expandedId;\n getScrollOffset = (): number => this.scrollOffset;\n // Get header\n getHeader = (): string | undefined => this.header;\n // Show status bar only if any process sets showStatusBar: true (default: false)\n getShowStatusBar = (): boolean => this.processes.some((p) => p.showStatusBar === true);\n // Interactive mode if any process has interactive: true\n getIsInteractive = (): boolean => this.processes.some((p) => p.interactive === true);\n isAllComplete = (): boolean => this.processes.length > 0 && this.processes.every((p) => p.state !== 'running');\n\n // Mutations - Ink handles render throttling at 30 FPS\n addProcess(process: ChildProcess): void {\n // Set header on first process that provides one\n if (this.header === undefined && process.header !== undefined) {\n this.header = process.header;\n }\n this.processes = [...this.processes, process];\n this.notify();\n }\n\n updateProcess(id: string, update: Partial<ChildProcess>): void {\n const oldProcess = this.processes.find((p) => p.id === id);\n const wasRunning = oldProcess?.state === 'running';\n const isNowComplete = update.state && update.state !== 'running';\n\n this.processes = this.processes.map((p) => (p.id === id ? { ...p, ...update } : p));\n\n // Track completion order\n if (wasRunning && isNowComplete && !this.completedIds.includes(id)) {\n this.completedIds = [...this.completedIds, id];\n }\n\n this.notify();\n }\n\n appendLines(id: string, newLines: Line[]): void {\n const process = this.processes.find((p) => p.id === id);\n if (process) {\n this.updateProcess(id, { lines: process.lines.concat(newLines) });\n }\n }\n\n getProcess(id: string): ChildProcess | undefined {\n return this.processes.find((p) => p.id === id);\n }\n\n // UI state mutations\n setMode(mode: Mode): void {\n this.mode = mode;\n if (mode === 'interactive') {\n this.selectedIndex = 0;\n } else if (mode === 'errorList') {\n this.selectedErrorIndex = 0;\n }\n this.notify();\n }\n\n // Interactive mode navigation\n selectNext(): void {\n if (this.processes.length > 0) {\n this.selectedIndex = (this.selectedIndex + 1) % this.processes.length;\n this.notify();\n }\n }\n\n selectPrev(): void {\n if (this.processes.length > 0) {\n this.selectedIndex = (this.selectedIndex - 1 + this.processes.length) % this.processes.length;\n this.notify();\n }\n }\n\n getSelectedProcess(): ChildProcess | undefined {\n return this.processes[this.selectedIndex];\n }\n\n selectNextError(): void {\n const failed = this.getFailedProcesses();\n if (failed.length > 0) {\n this.selectedErrorIndex = (this.selectedErrorIndex + 1) % failed.length;\n this.notify();\n }\n }\n\n selectPrevError(): void {\n const failed = this.getFailedProcesses();\n if (failed.length > 0) {\n this.selectedErrorIndex = (this.selectedErrorIndex - 1 + failed.length) % failed.length;\n this.notify();\n }\n }\n\n getSelectedError(): ChildProcess | undefined {\n const failed = this.getFailedProcesses();\n return failed[this.selectedErrorIndex];\n }\n\n // Expansion methods\n toggleExpand(): void {\n const selected = this.getSelectedProcess();\n if (!selected) return;\n\n if (this.expandedId === selected.id) {\n // Collapse\n this.expandedId = null;\n this.scrollOffset = 0;\n } else {\n // Expand\n this.expandedId = selected.id;\n this.scrollOffset = 0;\n }\n this.notify();\n }\n\n collapse(): void {\n this.expandedId = null;\n this.scrollOffset = 0;\n this.notify();\n }\n\n scrollDown(maxVisible: number): void {\n if (!this.expandedId) return;\n const process = this.getProcess(this.expandedId);\n if (!process) return;\n\n const maxOffset = Math.max(0, process.lines.length - maxVisible);\n if (this.scrollOffset < maxOffset) {\n this.scrollOffset++;\n this.notify();\n }\n }\n\n scrollUp(): void {\n if (!this.expandedId) return;\n if (this.scrollOffset > 0) {\n this.scrollOffset--;\n this.notify();\n }\n }\n\n // Exit signaling\n signalExit(callback: () => void): void {\n this.shouldExit = true;\n this.exitCallback = callback;\n this.notify();\n }\n\n getShouldExit = (): boolean => this.shouldExit;\n getExitCallback = (): (() => void) | null => this.exitCallback;\n\n reset(): void {\n this.processes = [];\n this.completedIds = [];\n this.shouldExit = false;\n this.exitCallback = null;\n this.mode = 'normal';\n this.selectedIndex = 0;\n this.selectedErrorIndex = 0;\n this.expandedId = null;\n this.scrollOffset = 0;\n this.header = undefined;\n }\n\n private notify(): void {\n this.listeners.forEach((l) => {\n l();\n });\n }\n}\n\nexport const processStore = new ProcessStore();\nexport type { ProcessStore };\n"],"names":["DEFAULT_COLUMN_WIDTH","LineType","ProcessStore","addProcess","process","header","undefined","processes","notify","updateProcess","id","update","oldProcess","find","p","wasRunning","state","isNowComplete","map","completedIds","includes","appendLines","newLines","lines","concat","getProcess","setMode","mode","selectedIndex","selectedErrorIndex","selectNext","length","selectPrev","getSelectedProcess","selectNextError","failed","getFailedProcesses","selectPrevError","getSelectedError","toggleExpand","selected","expandedId","scrollOffset","collapse","scrollDown","maxVisible","maxOffset","Math","max","scrollUp","signalExit","callback","shouldExit","exitCallback","reset","listeners","forEach","l","Set","subscribe","listener","add","delete","getSnapshot","getRunningProcesses","filter","getCompletedProcesses","getRunningCount","getMaxGroupLength","group","title","getDoneCount","getErrorCount","getErrorLineCount","reduce","total","type","stderr","getMode","getSelectedIndex","getSelectedErrorIndex","getExpandedId","getScrollOffset","getHeader","getShowStatusBar","some","showStatusBar","getIsInteractive","interactive","isAllComplete","every","getShouldExit","getExitCallback","processStore"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/types.ts"],"sourcesContent":["export type { SpawnCallback, SpawnError, SpawnOptions, SpawnResult } from 'cross-spawn-cb';\n\nimport type { SpawnError, SpawnResult } from 'cross-spawn-cb';\n\nexport type TerminalOptions = {\n group?: string;\n expanded?: boolean;\n};\n\nexport type TerminalCallback = (error?: SpawnError, result?: SpawnResult) => undefined;\n\nexport const LineType = {\n stdout: 1,\n stderr: 2,\n} as const;\n\nexport type Line = {\n type: (typeof LineType)[keyof typeof LineType];\n text: string;\n};\n\nexport type State = 'running' | 'error' | 'success';\nexport type ChildProcess = {\n id: string;\n group?: string;\n title: string;\n state: State;\n lines: Line[];\n expanded?: boolean;\n};\n"],"names":["LineType","stdout","stderr"],"mappings":"AAWA,OAAO,MAAMA,WAAW;IACtBC,QAAQ;IACRC,QAAQ;AACV,EAAW"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/types.ts"],"sourcesContent":["export type { SpawnCallback, SpawnError, SpawnOptions, SpawnResult } from 'cross-spawn-cb';\n\nimport type { SpawnError, SpawnResult } from 'cross-spawn-cb';\n\nexport type TerminalOptions = {\n group?: string;\n expanded?: boolean;\n header?: string;\n showStatusBar?: boolean;\n interactive?: boolean;\n};\n\nexport type TerminalCallback = (error?: SpawnError, result?: SpawnResult) => undefined;\n\nexport const LineType = {\n stdout: 1,\n stderr: 2,\n} as const;\n\nexport type Line = {\n type: (typeof LineType)[keyof typeof LineType];\n text: string;\n};\n\nexport type State = 'running' | 'error' | 'success';\nexport type ChildProcess = {\n id: string;\n group?: string;\n title: string;\n state: State;\n lines: Line[];\n expanded?: boolean;\n header?: string;\n showStatusBar?: boolean;\n interactive?: boolean;\n};\n"],"names":["LineType","stdout","stderr"],"mappings":"AAcA,OAAO,MAAMA,WAAW;IACtBC,QAAQ;IACRC,QAAQ;AACV,EAAW"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spawn-term",
3
- "version": "1.1.8",
3
+ "version": "2.1.0",
4
4
  "description": "Formats spawn with for terminal grouping",
5
5
  "keywords": [
6
6
  "spawn",