spawn-term 2.0.0 → 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 (49) hide show
  1. package/dist/cjs/components/App.js +79 -16
  2. package/dist/cjs/components/App.js.map +1 -1
  3. package/dist/cjs/components/CompactProcessLine.js +12 -3
  4. package/dist/cjs/components/CompactProcessLine.js.map +1 -1
  5. package/dist/cjs/components/ExpandedOutput.js +55 -0
  6. package/dist/cjs/components/ExpandedOutput.js.map +1 -0
  7. package/dist/cjs/constants.js +42 -0
  8. package/dist/cjs/constants.js.map +1 -0
  9. package/dist/cjs/createApp.js +11 -11
  10. package/dist/cjs/createApp.js.map +1 -1
  11. package/dist/cjs/lib/addLines.js +58 -4
  12. package/dist/cjs/lib/addLines.js.map +1 -1
  13. package/dist/cjs/lib/format.js +21 -0
  14. package/dist/cjs/lib/format.js.map +1 -0
  15. package/dist/cjs/src/components/CompactProcessLine.d.ts +1 -0
  16. package/dist/cjs/src/components/ExpandedOutput.d.ts +8 -0
  17. package/dist/cjs/src/constants.d.ts +7 -0
  18. package/dist/cjs/src/lib/addLines.d.ts +6 -1
  19. package/dist/cjs/src/lib/format.d.ts +2 -0
  20. package/dist/cjs/src/state/processStore.d.ts +20 -1
  21. package/dist/cjs/src/types.d.ts +6 -0
  22. package/dist/cjs/state/processStore.js +105 -1
  23. package/dist/cjs/state/processStore.js.map +1 -1
  24. package/dist/cjs/types.js.map +1 -1
  25. package/dist/esm/components/App.js +79 -14
  26. package/dist/esm/components/App.js.map +1 -1
  27. package/dist/esm/components/CompactProcessLine.js +12 -3
  28. package/dist/esm/components/CompactProcessLine.js.map +1 -1
  29. package/dist/esm/components/ExpandedOutput.js +41 -0
  30. package/dist/esm/components/ExpandedOutput.js.map +1 -0
  31. package/dist/esm/constants.js +11 -0
  32. package/dist/esm/constants.js.map +1 -0
  33. package/dist/esm/createApp.js +11 -11
  34. package/dist/esm/createApp.js.map +1 -1
  35. package/dist/esm/lib/addLines.js +32 -5
  36. package/dist/esm/lib/addLines.js.map +1 -1
  37. package/dist/esm/lib/format.js +10 -0
  38. package/dist/esm/lib/format.js.map +1 -0
  39. package/dist/esm/src/components/CompactProcessLine.d.ts +1 -0
  40. package/dist/esm/src/components/ExpandedOutput.d.ts +8 -0
  41. package/dist/esm/src/constants.d.ts +7 -0
  42. package/dist/esm/src/lib/addLines.d.ts +6 -1
  43. package/dist/esm/src/lib/format.d.ts +2 -0
  44. package/dist/esm/src/state/processStore.d.ts +20 -1
  45. package/dist/esm/src/types.d.ts +6 -0
  46. package/dist/esm/state/processStore.js +82 -1
  47. package/dist/esm/state/processStore.js.map +1 -1
  48. package/dist/esm/types.js.map +1 -1
  49. package/package.json +1 -1
@@ -0,0 +1,11 @@
1
+ // Column width defaults
2
+ export const DEFAULT_COLUMN_WIDTH = 15;
3
+ export const MAX_COLUMN_WIDTH_PERCENT = 0.4; // 40% of terminal width
4
+ export const FALLBACK_COLUMN_WIDTH = 25;
5
+ // Batching defaults
6
+ export const BATCH_MAX_LINES = 20;
7
+ export const BATCH_MAX_WAIT_MS = 50;
8
+ // Rendering
9
+ export const DEFAULT_MAX_FPS = 20;
10
+ // Expansion
11
+ export const EXPANDED_MAX_VISIBLE_LINES = 10;
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/constants.ts"],"sourcesContent":["// Column width defaults\nexport const DEFAULT_COLUMN_WIDTH = 15;\nexport const MAX_COLUMN_WIDTH_PERCENT = 0.4; // 40% of terminal width\nexport const FALLBACK_COLUMN_WIDTH = 25;\n\n// Batching defaults\nexport const BATCH_MAX_LINES = 20;\nexport const BATCH_MAX_WAIT_MS = 50;\n\n// Rendering\nexport const DEFAULT_MAX_FPS = 20;\n\n// Expansion\nexport const EXPANDED_MAX_VISIBLE_LINES = 10;\n"],"names":["DEFAULT_COLUMN_WIDTH","MAX_COLUMN_WIDTH_PERCENT","FALLBACK_COLUMN_WIDTH","BATCH_MAX_LINES","BATCH_MAX_WAIT_MS","DEFAULT_MAX_FPS","EXPANDED_MAX_VISIBLE_LINES"],"mappings":"AAAA,wBAAwB;AACxB,OAAO,MAAMA,uBAAuB,GAAG;AACvC,OAAO,MAAMC,2BAA2B,IAAI,CAAC,wBAAwB;AACrE,OAAO,MAAMC,wBAAwB,GAAG;AAExC,oBAAoB;AACpB,OAAO,MAAMC,kBAAkB,GAAG;AAClC,OAAO,MAAMC,oBAAoB,GAAG;AAEpC,YAAY;AACZ,OAAO,MAAMC,kBAAkB,GAAG;AAElC,YAAY;AACZ,OAAO,MAAMC,6BAA6B,GAAG"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { render } from 'ink';
3
3
  import App from './components/App.js';
4
+ import { DEFAULT_MAX_FPS } from './constants.js';
4
5
  import { processStore } from './state/processStore.js';
5
6
  export default function createApp() {
6
7
  let refCount = 0;
@@ -9,7 +10,11 @@ export default function createApp() {
9
10
  retain () {
10
11
  if (++refCount > 1) return processStore;
11
12
  // Render once - React handles all subsequent updates via useSyncExternalStore
12
- inkApp = render(/*#__PURE__*/ _jsx(App, {}));
13
+ // Enable incremental rendering to only rewrite changed lines (reduces flicker)
14
+ inkApp = render(/*#__PURE__*/ _jsx(App, {}), {
15
+ incrementalRendering: true,
16
+ maxFps: DEFAULT_MAX_FPS
17
+ });
13
18
  return processStore;
14
19
  },
15
20
  release (callback) {
@@ -18,16 +23,11 @@ export default function createApp() {
18
23
  return;
19
24
  }
20
25
  if (!inkApp) throw new Error('Expecting inkApp');
21
- // Defer signalExit to allow React's reconciliation to complete fully
22
- // Using setImmediate ensures we run after I/O callbacks and microtasks,
23
- // preventing the Static component from outputting the last item twice
24
- // (the second notify() from signalExit can race with Static's useLayoutEffect)
25
- setImmediate(()=>{
26
- processStore.signalExit(()=>{
27
- processStore.reset();
28
- process.stdout.write('\x1b[?25h'); // show cursor
29
- callback();
30
- });
26
+ // Signal exit to React component
27
+ processStore.signalExit(()=>{
28
+ processStore.reset();
29
+ process.stdout.write('\x1b[?25h'); // show cursor
30
+ callback();
31
31
  });
32
32
  // Wait for Ink to finish, then call the callback
33
33
  inkApp.waitUntilExit().then(()=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/createApp.tsx"],"sourcesContent":["import { render } from 'ink';\nimport App from './components/App.ts';\nimport { type ProcessStore, processStore } from './state/processStore.ts';\n\nexport type ReleaseCallback = () => void;\n\nexport default function createApp() {\n let refCount = 0;\n let inkApp: ReturnType<typeof render> | null = null;\n\n return {\n retain(): ProcessStore {\n if (++refCount > 1) return processStore;\n\n // Render once - React handles all subsequent updates via useSyncExternalStore\n inkApp = render(<App />);\n return processStore;\n },\n\n release(callback: ReleaseCallback): void {\n if (--refCount > 0) {\n callback();\n return;\n }\n if (!inkApp) throw new Error('Expecting inkApp');\n\n // Defer signalExit to allow React's reconciliation to complete fully\n // Using setImmediate ensures we run after I/O callbacks and microtasks,\n // preventing the Static component from outputting the last item twice\n // (the second notify() from signalExit can race with Static's useLayoutEffect)\n setImmediate(() => {\n processStore.signalExit(() => {\n processStore.reset();\n process.stdout.write('\\x1b[?25h'); // show cursor\n callback();\n });\n });\n\n // Wait for Ink to finish, then call the callback\n inkApp\n .waitUntilExit()\n .then(() => {\n const cb = processStore.getExitCallback();\n cb?.();\n })\n .catch(() => {\n const cb = processStore.getExitCallback();\n cb?.();\n });\n\n inkApp = null;\n },\n };\n}\n"],"names":["render","App","processStore","createApp","refCount","inkApp","retain","release","callback","Error","setImmediate","signalExit","reset","process","stdout","write","waitUntilExit","then","cb","getExitCallback","catch"],"mappings":";AAAA,SAASA,MAAM,QAAQ,MAAM;AAC7B,OAAOC,SAAS,sBAAsB;AACtC,SAA4BC,YAAY,QAAQ,0BAA0B;AAI1E,eAAe,SAASC;IACtB,IAAIC,WAAW;IACf,IAAIC,SAA2C;IAE/C,OAAO;QACLC;YACE,IAAI,EAAEF,WAAW,GAAG,OAAOF;YAE3B,8EAA8E;YAC9EG,SAASL,qBAAO,KAACC;YACjB,OAAOC;QACT;QAEAK,SAAQC,QAAyB;YAC/B,IAAI,EAAEJ,WAAW,GAAG;gBAClBI;gBACA;YACF;YACA,IAAI,CAACH,QAAQ,MAAM,IAAII,MAAM;YAE7B,qEAAqE;YACrE,wEAAwE;YACxE,sEAAsE;YACtE,+EAA+E;YAC/EC,aAAa;gBACXR,aAAaS,UAAU,CAAC;oBACtBT,aAAaU,KAAK;oBAClBC,QAAQC,MAAM,CAACC,KAAK,CAAC,cAAc,cAAc;oBACjDP;gBACF;YACF;YAEA,iDAAiD;YACjDH,OACGW,aAAa,GACbC,IAAI,CAAC;gBACJ,MAAMC,KAAKhB,aAAaiB,eAAe;gBACvCD,eAAAA,yBAAAA;YACF,GACCE,KAAK,CAAC;gBACL,MAAMF,KAAKhB,aAAaiB,eAAe;gBACvCD,eAAAA,yBAAAA;YACF;YAEFb,SAAS;QACX;IACF;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/createApp.tsx"],"sourcesContent":["import { render } from 'ink';\nimport App from './components/App.ts';\nimport { DEFAULT_MAX_FPS } from './constants.ts';\nimport { type ProcessStore, processStore } from './state/processStore.ts';\n\nexport type ReleaseCallback = () => void;\n\nexport default function createApp() {\n let refCount = 0;\n let inkApp: ReturnType<typeof render> | null = null;\n\n return {\n retain(): ProcessStore {\n if (++refCount > 1) return processStore;\n\n // Render once - React handles all subsequent updates via useSyncExternalStore\n // Enable incremental rendering to only rewrite changed lines (reduces flicker)\n inkApp = render(<App />, {\n incrementalRendering: true,\n maxFps: DEFAULT_MAX_FPS,\n });\n return processStore;\n },\n\n release(callback: ReleaseCallback): void {\n if (--refCount > 0) {\n callback();\n return;\n }\n if (!inkApp) throw new Error('Expecting inkApp');\n\n // Signal exit to React component\n processStore.signalExit(() => {\n processStore.reset();\n process.stdout.write('\\x1b[?25h'); // show cursor\n callback();\n });\n\n // Wait for Ink to finish, then call the callback\n inkApp\n .waitUntilExit()\n .then(() => {\n const cb = processStore.getExitCallback();\n cb?.();\n })\n .catch(() => {\n const cb = processStore.getExitCallback();\n cb?.();\n });\n\n inkApp = null;\n },\n };\n}\n"],"names":["render","App","DEFAULT_MAX_FPS","processStore","createApp","refCount","inkApp","retain","incrementalRendering","maxFps","release","callback","Error","signalExit","reset","process","stdout","write","waitUntilExit","then","cb","getExitCallback","catch"],"mappings":";AAAA,SAASA,MAAM,QAAQ,MAAM;AAC7B,OAAOC,SAAS,sBAAsB;AACtC,SAASC,eAAe,QAAQ,iBAAiB;AACjD,SAA4BC,YAAY,QAAQ,0BAA0B;AAI1E,eAAe,SAASC;IACtB,IAAIC,WAAW;IACf,IAAIC,SAA2C;IAE/C,OAAO;QACLC;YACE,IAAI,EAAEF,WAAW,GAAG,OAAOF;YAE3B,8EAA8E;YAC9E,+EAA+E;YAC/EG,SAASN,qBAAO,KAACC,UAAQ;gBACvBO,sBAAsB;gBACtBC,QAAQP;YACV;YACA,OAAOC;QACT;QAEAO,SAAQC,QAAyB;YAC/B,IAAI,EAAEN,WAAW,GAAG;gBAClBM;gBACA;YACF;YACA,IAAI,CAACL,QAAQ,MAAM,IAAIM,MAAM;YAE7B,iCAAiC;YACjCT,aAAaU,UAAU,CAAC;gBACtBV,aAAaW,KAAK;gBAClBC,QAAQC,MAAM,CAACC,KAAK,CAAC,cAAc,cAAc;gBACjDN;YACF;YAEA,iDAAiD;YACjDL,OACGY,aAAa,GACbC,IAAI,CAAC;gBACJ,MAAMC,KAAKjB,aAAakB,eAAe;gBACvCD,eAAAA,yBAAAA;YACF,GACCE,KAAK,CAAC;gBACL,MAAMF,KAAKjB,aAAakB,eAAe;gBACvCD,eAAAA,yBAAAA;YACF;YAEFd,SAAS;QACX;IACF;AACF"}
@@ -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"}
@@ -1,6 +1,7 @@
1
1
  import type { ChildProcess } from '../types.js';
2
2
  type Props = {
3
3
  item: ChildProcess;
4
+ isSelected?: boolean;
4
5
  };
5
6
  declare const _default: import("react").NamedExoticComponent<Props>;
6
7
  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,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,6 +1,6 @@
1
1
  import type { ChildProcess, Line } from '../types.js';
2
2
  type Listener = () => void;
3
- type Mode = 'normal' | 'errorList' | 'errorDetail';
3
+ type Mode = 'normal' | 'interactive' | 'errorList' | 'errorDetail';
4
4
  declare class ProcessStore {
5
5
  private processes;
6
6
  private completedIds;
@@ -8,26 +8,45 @@ declare class ProcessStore {
8
8
  private shouldExit;
9
9
  private exitCallback;
10
10
  private mode;
11
+ private selectedIndex;
11
12
  private selectedErrorIndex;
13
+ private expandedId;
14
+ private scrollOffset;
15
+ private header;
12
16
  subscribe: (listener: Listener) => (() => void);
13
17
  getSnapshot: () => ChildProcess[];
14
18
  getRunningProcesses: () => ChildProcess[];
15
19
  getCompletedProcesses: () => ChildProcess[];
16
20
  getFailedProcesses: () => ChildProcess[];
17
21
  getRunningCount: () => number;
22
+ getMaxGroupLength: () => number;
18
23
  getDoneCount: () => number;
19
24
  getErrorCount: () => number;
20
25
  getErrorLineCount: () => number;
21
26
  getMode: () => Mode;
27
+ getSelectedIndex: () => number;
22
28
  getSelectedErrorIndex: () => number;
29
+ getExpandedId: () => string | null;
30
+ getScrollOffset: () => number;
31
+ getHeader: () => string | undefined;
32
+ getShowStatusBar: () => boolean;
33
+ getIsInteractive: () => boolean;
34
+ isAllComplete: () => boolean;
23
35
  addProcess(process: ChildProcess): void;
24
36
  updateProcess(id: string, update: Partial<ChildProcess>): void;
25
37
  appendLines(id: string, newLines: Line[]): void;
26
38
  getProcess(id: string): ChildProcess | undefined;
27
39
  setMode(mode: Mode): void;
40
+ selectNext(): void;
41
+ selectPrev(): void;
42
+ getSelectedProcess(): ChildProcess | undefined;
28
43
  selectNextError(): void;
29
44
  selectPrevError(): void;
30
45
  getSelectedError(): ChildProcess | undefined;
46
+ toggleExpand(): void;
47
+ collapse(): void;
48
+ scrollDown(maxVisible: number): void;
49
+ scrollUp(): void;
31
50
  signalExit(callback: () => void): void;
32
51
  getShouldExit: () => boolean;
33
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,10 +26,15 @@ function _object_spread(target) {
26
26
  }
27
27
  return target;
28
28
  }
29
+ import { DEFAULT_COLUMN_WIDTH } from '../constants.js';
29
30
  import { LineType } from '../types.js';
30
31
  class ProcessStore {
31
32
  // Mutations - Ink handles render throttling at 30 FPS
32
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
+ }
33
38
  this.processes = [
34
39
  ...this.processes,
35
40
  process
@@ -64,11 +69,29 @@ class ProcessStore {
64
69
  // UI state mutations
65
70
  setMode(mode) {
66
71
  this.mode = mode;
67
- if (mode === 'errorList') {
72
+ if (mode === 'interactive') {
73
+ this.selectedIndex = 0;
74
+ } else if (mode === 'errorList') {
68
75
  this.selectedErrorIndex = 0;
69
76
  }
70
77
  this.notify();
71
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
+ }
72
95
  selectNextError() {
73
96
  const failed = this.getFailedProcesses();
74
97
  if (failed.length > 0) {
@@ -87,6 +110,43 @@ class ProcessStore {
87
110
  const failed = this.getFailedProcesses();
88
111
  return failed[this.selectedErrorIndex];
89
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
+ }
90
150
  // Exit signaling
91
151
  signalExit(callback) {
92
152
  this.shouldExit = true;
@@ -99,7 +159,11 @@ class ProcessStore {
99
159
  this.shouldExit = false;
100
160
  this.exitCallback = null;
101
161
  this.mode = 'normal';
162
+ this.selectedIndex = 0;
102
163
  this.selectedErrorIndex = 0;
164
+ this.expandedId = null;
165
+ this.scrollOffset = 0;
166
+ this.header = undefined;
103
167
  }
104
168
  notify() {
105
169
  this.listeners.forEach((l)=>{
@@ -114,7 +178,10 @@ class ProcessStore {
114
178
  this.exitCallback = null;
115
179
  // UI state
116
180
  this.mode = 'normal';
181
+ this.selectedIndex = 0;
117
182
  this.selectedErrorIndex = 0;
183
+ this.expandedId = null;
184
+ this.scrollOffset = 0;
118
185
  // useSyncExternalStore API
119
186
  this.subscribe = (listener)=>{
120
187
  this.listeners.add(listener);
@@ -134,6 +201,10 @@ class ProcessStore {
134
201
  };
135
202
  // Counts
136
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
+ };
137
208
  this.getDoneCount = ()=>this.processes.filter((p)=>p.state !== 'running').length;
138
209
  this.getErrorCount = ()=>this.processes.filter((p)=>p.state === 'error').length;
139
210
  this.getErrorLineCount = ()=>{
@@ -141,7 +212,17 @@ class ProcessStore {
141
212
  };
142
213
  // UI state getters
143
214
  this.getMode = ()=>this.mode;
215
+ this.getSelectedIndex = ()=>this.selectedIndex;
144
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');
145
226
  this.getShouldExit = ()=>this.shouldExit;
146
227
  this.getExitCallback = ()=>this.exitCallback;
147
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';\nimport { LineType } from '../types.ts';\n\ntype Listener = () => void;\ntype Mode = 'normal' | '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 selectedErrorIndex = 0;\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 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 getSelectedErrorIndex = (): number => this.selectedErrorIndex;\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 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 === 'errorList') {\n this.selectedErrorIndex = 0;\n }\n this.notify();\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 // 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.selectedErrorIndex = 0;\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":["LineType","ProcessStore","addProcess","process","processes","notify","updateProcess","id","update","oldProcess","find","p","wasRunning","state","isNowComplete","map","completedIds","includes","appendLines","newLines","lines","concat","getProcess","setMode","mode","selectedErrorIndex","selectNextError","failed","getFailedProcesses","length","selectPrevError","getSelectedError","signalExit","callback","shouldExit","exitCallback","reset","listeners","forEach","l","Set","subscribe","listener","add","delete","getSnapshot","getRunningProcesses","filter","getCompletedProcesses","undefined","getRunningCount","getDoneCount","getErrorCount","getErrorLineCount","reduce","total","type","stderr","getMode","getSelectedErrorIndex","getShouldExit","getExitCallback","processStore"],"mappings":"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"}
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": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Formats spawn with for terminal grouping",
5
5
  "keywords": [
6
6
  "spawn",