spawn-term 2.1.1 → 3.0.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 (63) hide show
  1. package/dist/cjs/components/App.js +62 -46
  2. package/dist/cjs/components/App.js.map +1 -1
  3. package/dist/cjs/components/CompactProcessLine.js +3 -2
  4. package/dist/cjs/components/CompactProcessLine.js.map +1 -1
  5. package/dist/cjs/index-cjs.js +3 -3
  6. package/dist/cjs/index-cjs.js.map +1 -1
  7. package/dist/cjs/index-esm.js +4 -4
  8. package/dist/cjs/index-esm.js.map +1 -1
  9. package/dist/cjs/session.js +311 -0
  10. package/dist/cjs/session.js.map +1 -0
  11. package/dist/cjs/src/components/App.d.ts +6 -1
  12. package/dist/cjs/src/index-cjs.d.ts +3 -3
  13. package/dist/cjs/src/index-esm.d.ts +3 -3
  14. package/dist/cjs/src/session.d.ts +7 -0
  15. package/dist/cjs/src/state/StoreContext.d.ts +3 -0
  16. package/dist/cjs/src/state/processStore.d.ts +6 -4
  17. package/dist/cjs/src/types.d.ts +5 -6
  18. package/dist/cjs/state/StoreContext.js +28 -0
  19. package/dist/cjs/state/StoreContext.js.map +1 -0
  20. package/dist/cjs/state/processStore.js +15 -17
  21. package/dist/cjs/state/processStore.js.map +1 -1
  22. package/dist/cjs/types.js.map +1 -1
  23. package/dist/esm/components/App.js +59 -45
  24. package/dist/esm/components/App.js.map +1 -1
  25. package/dist/esm/components/CompactProcessLine.js +3 -2
  26. package/dist/esm/components/CompactProcessLine.js.map +1 -1
  27. package/dist/esm/index-cjs.js +1 -1
  28. package/dist/esm/index-cjs.js.map +1 -1
  29. package/dist/esm/index-esm.js +2 -2
  30. package/dist/esm/index-esm.js.map +1 -1
  31. package/dist/esm/session.js +218 -0
  32. package/dist/esm/session.js.map +1 -0
  33. package/dist/esm/src/components/App.d.ts +6 -1
  34. package/dist/esm/src/index-cjs.d.ts +3 -3
  35. package/dist/esm/src/index-esm.d.ts +3 -3
  36. package/dist/esm/src/session.d.ts +7 -0
  37. package/dist/esm/src/state/StoreContext.d.ts +3 -0
  38. package/dist/esm/src/state/processStore.d.ts +6 -4
  39. package/dist/esm/src/types.d.ts +5 -6
  40. package/dist/esm/state/StoreContext.js +9 -0
  41. package/dist/esm/state/StoreContext.js.map +1 -0
  42. package/dist/esm/state/processStore.js +13 -13
  43. package/dist/esm/state/processStore.js.map +1 -1
  44. package/dist/esm/types.js.map +1 -1
  45. package/package.json +1 -1
  46. package/dist/cjs/createApp.js +0 -58
  47. package/dist/cjs/createApp.js.map +0 -1
  48. package/dist/cjs/spawnTerminal.js +0 -75
  49. package/dist/cjs/spawnTerminal.js.map +0 -1
  50. package/dist/cjs/src/createApp.d.ts +0 -6
  51. package/dist/cjs/src/spawnTerminal.d.ts +0 -2
  52. package/dist/cjs/src/worker.d.ts +0 -2
  53. package/dist/cjs/worker.js +0 -236
  54. package/dist/cjs/worker.js.map +0 -1
  55. package/dist/esm/createApp.js +0 -42
  56. package/dist/esm/createApp.js.map +0 -1
  57. package/dist/esm/spawnTerminal.js +0 -19
  58. package/dist/esm/spawnTerminal.js.map +0 -1
  59. package/dist/esm/src/createApp.d.ts +0 -6
  60. package/dist/esm/src/spawnTerminal.d.ts +0 -2
  61. package/dist/esm/src/worker.d.ts +0 -2
  62. package/dist/esm/worker.js +0 -175
  63. package/dist/esm/worker.js.map +0 -1
@@ -2,7 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, "default", {
5
+ Object.defineProperty(exports, // Wrapper component that provides store context
6
+ "default", {
6
7
  enumerable: true,
7
8
  get: function() {
8
9
  return App;
@@ -12,7 +13,7 @@ var _jsxruntime = require("react/jsx-runtime");
12
13
  var _ink = require("ink");
13
14
  var _react = require("react");
14
15
  var _constantsts = require("../constants.js");
15
- var _processStorets = require("../state/processStore.js");
16
+ var _StoreContextts = require("../state/StoreContext.js");
16
17
  var _CompactProcessLinets = /*#__PURE__*/ _interop_require_default(require("./CompactProcessLine.js"));
17
18
  var _Dividerts = /*#__PURE__*/ _interop_require_default(require("./Divider.js"));
18
19
  var _ErrorDetailModalts = /*#__PURE__*/ _interop_require_default(require("./ErrorDetailModal.js"));
@@ -24,28 +25,29 @@ function _interop_require_default(obj) {
24
25
  default: obj
25
26
  };
26
27
  }
27
- function App() {
28
+ function AppContent(param) {
29
+ var store = param.store;
28
30
  var exit = (0, _ink.useApp)().exit;
29
31
  var isRawModeSupported = (0, _ink.useStdin)().isRawModeSupported;
30
32
  // Subscribe to store state
31
- var processes = (0, _react.useSyncExternalStore)(_processStorets.processStore.subscribe, _processStorets.processStore.getSnapshot);
32
- var shouldExit = (0, _react.useSyncExternalStore)(_processStorets.processStore.subscribe, _processStorets.processStore.getShouldExit);
33
- var mode = (0, _react.useSyncExternalStore)(_processStorets.processStore.subscribe, _processStorets.processStore.getMode);
34
- var selectedIndex = (0, _react.useSyncExternalStore)(_processStorets.processStore.subscribe, _processStorets.processStore.getSelectedIndex);
35
- var selectedErrorIndex = (0, _react.useSyncExternalStore)(_processStorets.processStore.subscribe, _processStorets.processStore.getSelectedErrorIndex);
36
- var expandedId = (0, _react.useSyncExternalStore)(_processStorets.processStore.subscribe, _processStorets.processStore.getExpandedId);
37
- var scrollOffset = (0, _react.useSyncExternalStore)(_processStorets.processStore.subscribe, _processStorets.processStore.getScrollOffset);
33
+ var processes = (0, _react.useSyncExternalStore)(store.subscribe, store.getSnapshot);
34
+ var shouldExit = (0, _react.useSyncExternalStore)(store.subscribe, store.getShouldExit);
35
+ var mode = (0, _react.useSyncExternalStore)(store.subscribe, store.getMode);
36
+ var selectedIndex = (0, _react.useSyncExternalStore)(store.subscribe, store.getSelectedIndex);
37
+ var selectedErrorIndex = (0, _react.useSyncExternalStore)(store.subscribe, store.getSelectedErrorIndex);
38
+ var expandedId = (0, _react.useSyncExternalStore)(store.subscribe, store.getExpandedId);
39
+ var scrollOffset = (0, _react.useSyncExternalStore)(store.subscribe, store.getScrollOffset);
38
40
  // Subscribed state that triggers re-renders
39
- var header = (0, _react.useSyncExternalStore)(_processStorets.processStore.subscribe, _processStorets.processStore.getHeader);
40
- var showStatusBar = (0, _react.useSyncExternalStore)(_processStorets.processStore.subscribe, _processStorets.processStore.getShowStatusBar);
41
- var isInteractive = (0, _react.useSyncExternalStore)(_processStorets.processStore.subscribe, _processStorets.processStore.getIsInteractive);
41
+ var header = (0, _react.useSyncExternalStore)(store.subscribe, store.getHeader);
42
+ var showStatusBar = (0, _react.useSyncExternalStore)(store.subscribe, store.getShowStatusBar);
43
+ var isInteractive = (0, _react.useSyncExternalStore)(store.subscribe, store.getIsInteractive);
42
44
  // Derived state (computed from processes which is already subscribed)
43
- var failedProcesses = _processStorets.processStore.getFailedProcesses();
44
- var runningCount = _processStorets.processStore.getRunningCount();
45
- var doneCount = _processStorets.processStore.getDoneCount();
46
- var errorCount = _processStorets.processStore.getErrorCount();
47
- var errorLineCount = _processStorets.processStore.getErrorLineCount();
48
- var isAllComplete = _processStorets.processStore.isAllComplete();
45
+ var failedProcesses = store.getFailedProcesses();
46
+ var runningCount = store.getRunningCount();
47
+ var doneCount = store.getDoneCount();
48
+ var errorCount = store.getErrorCount();
49
+ var errorLineCount = store.getErrorLineCount();
50
+ var isAllComplete = store.isAllComplete();
49
51
  // Handle exit signal
50
52
  (0, _react.useEffect)(function() {
51
53
  if (shouldExit) {
@@ -58,72 +60,73 @@ function App() {
58
60
  // Auto-enter interactive mode when all complete and interactive flag is set
59
61
  (0, _react.useEffect)(function() {
60
62
  if (isAllComplete && isInteractive && mode === 'normal') {
61
- _processStorets.processStore.setMode('interactive');
63
+ store.setMode('interactive');
62
64
  }
63
65
  }, [
64
66
  isAllComplete,
65
67
  isInteractive,
66
- mode
68
+ mode,
69
+ store
67
70
  ]);
68
71
  // Keyboard handling (only active when raw mode is supported)
69
72
  (0, _ink.useInput)(function(input, key) {
70
73
  if (mode === 'normal') {
71
74
  if (input === 'e' && errorCount > 0) {
72
- _processStorets.processStore.setMode('errorList');
75
+ store.setMode('errorList');
73
76
  }
74
77
  } else if (mode === 'interactive') {
75
78
  if (input === 'q' || key.escape) {
76
79
  if (expandedId) {
77
- _processStorets.processStore.collapse();
80
+ store.collapse();
78
81
  } else {
79
- _processStorets.processStore.signalExit(function() {});
82
+ store.signalExit(function() {});
80
83
  }
81
84
  } else if (key.return) {
82
- _processStorets.processStore.toggleExpand();
85
+ store.toggleExpand();
83
86
  } else if (key.downArrow) {
84
87
  if (expandedId) {
85
- _processStorets.processStore.scrollDown(_constantsts.EXPANDED_MAX_VISIBLE_LINES);
88
+ store.scrollDown(_constantsts.EXPANDED_MAX_VISIBLE_LINES);
86
89
  } else {
87
- _processStorets.processStore.selectNext();
90
+ store.selectNext();
88
91
  }
89
92
  } else if (key.upArrow) {
90
93
  if (expandedId) {
91
- _processStorets.processStore.scrollUp();
94
+ store.scrollUp();
92
95
  } else {
93
- _processStorets.processStore.selectPrev();
96
+ store.selectPrev();
94
97
  }
95
98
  } else if (input === 'j') {
96
99
  if (expandedId) {
97
- _processStorets.processStore.scrollDown(_constantsts.EXPANDED_MAX_VISIBLE_LINES);
100
+ store.scrollDown(_constantsts.EXPANDED_MAX_VISIBLE_LINES);
98
101
  } else {
99
- _processStorets.processStore.selectNext();
102
+ store.selectNext();
100
103
  }
101
104
  } else if (input === 'k') {
102
105
  if (expandedId) {
103
- _processStorets.processStore.scrollUp();
106
+ store.scrollUp();
104
107
  } else {
105
- _processStorets.processStore.selectPrev();
108
+ store.selectPrev();
106
109
  }
107
110
  } else if (input === 'e' && errorCount > 0) {
108
- _processStorets.processStore.setMode('errorList');
111
+ store.setMode('errorList');
109
112
  }
110
113
  } else if (mode === 'errorList') {
111
114
  if (key.escape) {
112
- _processStorets.processStore.setMode(isInteractive ? 'interactive' : 'normal');
115
+ store.setMode(isInteractive ? 'interactive' : 'normal');
113
116
  } else if (key.downArrow) {
114
- _processStorets.processStore.selectNextError();
117
+ store.selectNextError();
115
118
  } else if (key.upArrow) {
116
- _processStorets.processStore.selectPrevError();
119
+ store.selectPrevError();
117
120
  } else if (key.return) {
118
- _processStorets.processStore.setMode('errorDetail');
121
+ store.setMode('errorDetail');
119
122
  }
120
123
  } else if (mode === 'errorDetail') {
121
124
  if (key.escape) {
122
- _processStorets.processStore.setMode('errorList');
125
+ store.setMode('errorList');
123
126
  } else if (key.downArrow) {
124
- _processStorets.processStore.selectNextError();
127
+ store.selectNextError();
125
128
  } else if (key.upArrow) {
126
- _processStorets.processStore.selectPrevError();
129
+ store.selectPrevError();
127
130
  }
128
131
  }
129
132
  }, {
@@ -139,7 +142,7 @@ function App() {
139
142
  }
140
143
  // Error detail modal
141
144
  if (mode === 'errorDetail') {
142
- var selectedError = _processStorets.processStore.getSelectedError();
145
+ var selectedError = store.getSelectedError();
143
146
  if (selectedError) {
144
147
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_ErrorDetailModalts.default, {
145
148
  error: selectedError,
@@ -148,17 +151,21 @@ function App() {
148
151
  });
149
152
  }
150
153
  // Fallback if no error selected
151
- _processStorets.processStore.setMode('errorList');
154
+ store.setMode('errorList');
152
155
  }
153
156
  // Normal/Interactive view - render in original registration order
154
157
  var showSelection = mode === 'interactive';
155
158
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Box, {
156
159
  flexDirection: "column",
157
160
  children: [
158
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
159
- children: header || '(loading...)'
161
+ header && /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
162
+ children: [
163
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_ink.Text, {
164
+ children: header
165
+ }),
166
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_Dividerts.default, {})
167
+ ]
160
168
  }),
161
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_Dividerts.default, {}),
162
169
  processes.map(function(item, index) {
163
170
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ink.Box, {
164
171
  flexDirection: "column",
@@ -188,4 +195,13 @@ function App() {
188
195
  ]
189
196
  });
190
197
  }
198
+ function App(param) {
199
+ var store = param.store;
200
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_StoreContextts.StoreContext.Provider, {
201
+ value: store,
202
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(AppContent, {
203
+ store: store
204
+ })
205
+ });
206
+ }
191
207
  /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/components/App.tsx"],"sourcesContent":["import { Box, Text, useApp, useInput, useStdin } from 'ink';\nimport { useEffect, useSyncExternalStore } from 'react';\nimport { EXPANDED_MAX_VISIBLE_LINES } from '../constants.ts';\nimport { processStore } from '../state/processStore.ts';\nimport CompactProcessLine from './CompactProcessLine.ts';\nimport Divider from './Divider.ts';\nimport ErrorDetailModal from './ErrorDetailModal.ts';\nimport ErrorListModal from './ErrorListModal.ts';\nimport ExpandedOutput from './ExpandedOutput.ts';\nimport StatusBar from './StatusBar.ts';\n\nexport default function App(): React.JSX.Element {\n const { exit } = useApp();\n const { isRawModeSupported } = useStdin();\n\n // Subscribe to store state\n const processes = useSyncExternalStore(processStore.subscribe, processStore.getSnapshot);\n const shouldExit = useSyncExternalStore(processStore.subscribe, processStore.getShouldExit);\n const mode = useSyncExternalStore(processStore.subscribe, processStore.getMode);\n const selectedIndex = useSyncExternalStore(processStore.subscribe, processStore.getSelectedIndex);\n const selectedErrorIndex = useSyncExternalStore(processStore.subscribe, processStore.getSelectedErrorIndex);\n const expandedId = useSyncExternalStore(processStore.subscribe, processStore.getExpandedId);\n const scrollOffset = useSyncExternalStore(processStore.subscribe, processStore.getScrollOffset);\n\n // Subscribed state that triggers re-renders\n const header = useSyncExternalStore(processStore.subscribe, processStore.getHeader);\n const showStatusBar = useSyncExternalStore(processStore.subscribe, processStore.getShowStatusBar);\n const isInteractive = useSyncExternalStore(processStore.subscribe, processStore.getIsInteractive);\n\n // Derived state (computed from processes which is already subscribed)\n const failedProcesses = processStore.getFailedProcesses();\n const runningCount = processStore.getRunningCount();\n const doneCount = processStore.getDoneCount();\n const errorCount = processStore.getErrorCount();\n const errorLineCount = processStore.getErrorLineCount();\n const isAllComplete = processStore.isAllComplete();\n\n // Handle exit signal\n useEffect(() => {\n if (shouldExit) {\n exit();\n }\n }, [shouldExit, exit]);\n\n // Auto-enter interactive mode when all complete and interactive flag is set\n useEffect(() => {\n if (isAllComplete && isInteractive && mode === 'normal') {\n processStore.setMode('interactive');\n }\n }, [isAllComplete, isInteractive, mode]);\n\n // Keyboard handling (only active when raw mode is supported)\n useInput(\n (input, key) => {\n if (mode === 'normal') {\n if (input === 'e' && errorCount > 0) {\n processStore.setMode('errorList');\n }\n } else if (mode === 'interactive') {\n if (input === 'q' || key.escape) {\n if (expandedId) {\n processStore.collapse();\n } else {\n processStore.signalExit(() => {});\n }\n } else if (key.return) {\n processStore.toggleExpand();\n } else if (key.downArrow) {\n if (expandedId) {\n processStore.scrollDown(EXPANDED_MAX_VISIBLE_LINES);\n } else {\n processStore.selectNext();\n }\n } else if (key.upArrow) {\n if (expandedId) {\n processStore.scrollUp();\n } else {\n processStore.selectPrev();\n }\n } else if (input === 'j') {\n if (expandedId) {\n processStore.scrollDown(EXPANDED_MAX_VISIBLE_LINES);\n } else {\n processStore.selectNext();\n }\n } else if (input === 'k') {\n if (expandedId) {\n processStore.scrollUp();\n } else {\n processStore.selectPrev();\n }\n } else if (input === 'e' && errorCount > 0) {\n processStore.setMode('errorList');\n }\n } else if (mode === 'errorList') {\n if (key.escape) {\n processStore.setMode(isInteractive ? 'interactive' : 'normal');\n } else if (key.downArrow) {\n processStore.selectNextError();\n } else if (key.upArrow) {\n processStore.selectPrevError();\n } else if (key.return) {\n processStore.setMode('errorDetail');\n }\n } else if (mode === 'errorDetail') {\n if (key.escape) {\n processStore.setMode('errorList');\n } else if (key.downArrow) {\n processStore.selectNextError();\n } else if (key.upArrow) {\n processStore.selectPrevError();\n }\n }\n },\n { isActive: isRawModeSupported === true }\n );\n\n // Error list modal\n if (mode === 'errorList') {\n return <ErrorListModal errors={failedProcesses} selectedIndex={selectedErrorIndex} totalErrorLines={errorLineCount} />;\n }\n\n // Error detail modal\n if (mode === 'errorDetail') {\n const selectedError = processStore.getSelectedError();\n if (selectedError) {\n return <ErrorDetailModal error={selectedError} currentIndex={selectedErrorIndex} totalErrors={failedProcesses.length} />;\n }\n // Fallback if no error selected\n processStore.setMode('errorList');\n }\n\n // Normal/Interactive view - render in original registration order\n const showSelection = mode === 'interactive';\n return (\n <Box flexDirection=\"column\">\n {/* Header - always render a line */}\n <Text>{header || '(loading...)'}</Text>\n <Divider />\n\n {/* All processes in registration order */}\n {processes.map((item, index) => (\n <Box key={item.id} flexDirection=\"column\">\n <CompactProcessLine item={item} isSelected={showSelection && index === selectedIndex} />\n {expandedId === item.id && <ExpandedOutput lines={item.lines} scrollOffset={scrollOffset} />}\n </Box>\n ))}\n\n {/* Status bar */}\n {showStatusBar && processes.length > 0 && (\n <>\n <Divider />\n <StatusBar running={runningCount} done={doneCount} errors={errorCount} errorLines={errorLineCount} />\n </>\n )}\n </Box>\n );\n}\n"],"names":["App","exit","useApp","isRawModeSupported","useStdin","processes","useSyncExternalStore","processStore","subscribe","getSnapshot","shouldExit","getShouldExit","mode","getMode","selectedIndex","getSelectedIndex","selectedErrorIndex","getSelectedErrorIndex","expandedId","getExpandedId","scrollOffset","getScrollOffset","header","getHeader","showStatusBar","getShowStatusBar","isInteractive","getIsInteractive","failedProcesses","getFailedProcesses","runningCount","getRunningCount","doneCount","getDoneCount","errorCount","getErrorCount","errorLineCount","getErrorLineCount","isAllComplete","useEffect","setMode","useInput","input","key","escape","collapse","signalExit","return","toggleExpand","downArrow","scrollDown","EXPANDED_MAX_VISIBLE_LINES","selectNext","upArrow","scrollUp","selectPrev","selectNextError","selectPrevError","isActive","ErrorListModal","errors","totalErrorLines","selectedError","getSelectedError","ErrorDetailModal","error","currentIndex","totalErrors","length","showSelection","Box","flexDirection","Text","Divider","map","item","index","CompactProcessLine","isSelected","id","ExpandedOutput","lines","StatusBar","running","done","errorLines"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/components/App.tsx"],"sourcesContent":["import { Box, Text, useApp, useInput, useStdin } from 'ink';\nimport { useEffect, useSyncExternalStore } from 'react';\nimport { EXPANDED_MAX_VISIBLE_LINES } from '../constants.ts';\nimport type { ProcessStore } from '../state/processStore.ts';\nimport { StoreContext } from '../state/StoreContext.ts';\nimport CompactProcessLine from './CompactProcessLine.ts';\nimport Divider from './Divider.ts';\nimport ErrorDetailModal from './ErrorDetailModal.ts';\nimport ErrorListModal from './ErrorListModal.ts';\nimport ExpandedOutput from './ExpandedOutput.ts';\nimport StatusBar from './StatusBar.ts';\n\ninterface AppProps {\n store: ProcessStore;\n}\n\nfunction AppContent({ store }: AppProps): React.JSX.Element {\n const { exit } = useApp();\n const { isRawModeSupported } = useStdin();\n\n // Subscribe to store state\n const processes = useSyncExternalStore(store.subscribe, store.getSnapshot);\n const shouldExit = useSyncExternalStore(store.subscribe, store.getShouldExit);\n const mode = useSyncExternalStore(store.subscribe, store.getMode);\n const selectedIndex = useSyncExternalStore(store.subscribe, store.getSelectedIndex);\n const selectedErrorIndex = useSyncExternalStore(store.subscribe, store.getSelectedErrorIndex);\n const expandedId = useSyncExternalStore(store.subscribe, store.getExpandedId);\n const scrollOffset = useSyncExternalStore(store.subscribe, store.getScrollOffset);\n\n // Subscribed state that triggers re-renders\n const header = useSyncExternalStore(store.subscribe, store.getHeader);\n const showStatusBar = useSyncExternalStore(store.subscribe, store.getShowStatusBar);\n const isInteractive = useSyncExternalStore(store.subscribe, store.getIsInteractive);\n\n // Derived state (computed from processes which is already subscribed)\n const failedProcesses = store.getFailedProcesses();\n const runningCount = store.getRunningCount();\n const doneCount = store.getDoneCount();\n const errorCount = store.getErrorCount();\n const errorLineCount = store.getErrorLineCount();\n const isAllComplete = store.isAllComplete();\n\n // Handle exit signal\n useEffect(() => {\n if (shouldExit) {\n exit();\n }\n }, [shouldExit, exit]);\n\n // Auto-enter interactive mode when all complete and interactive flag is set\n useEffect(() => {\n if (isAllComplete && isInteractive && mode === 'normal') {\n store.setMode('interactive');\n }\n }, [isAllComplete, isInteractive, mode, store]);\n\n // Keyboard handling (only active when raw mode is supported)\n useInput(\n (input, key) => {\n if (mode === 'normal') {\n if (input === 'e' && errorCount > 0) {\n store.setMode('errorList');\n }\n } else if (mode === 'interactive') {\n if (input === 'q' || key.escape) {\n if (expandedId) {\n store.collapse();\n } else {\n store.signalExit(() => {});\n }\n } else if (key.return) {\n store.toggleExpand();\n } else if (key.downArrow) {\n if (expandedId) {\n store.scrollDown(EXPANDED_MAX_VISIBLE_LINES);\n } else {\n store.selectNext();\n }\n } else if (key.upArrow) {\n if (expandedId) {\n store.scrollUp();\n } else {\n store.selectPrev();\n }\n } else if (input === 'j') {\n if (expandedId) {\n store.scrollDown(EXPANDED_MAX_VISIBLE_LINES);\n } else {\n store.selectNext();\n }\n } else if (input === 'k') {\n if (expandedId) {\n store.scrollUp();\n } else {\n store.selectPrev();\n }\n } else if (input === 'e' && errorCount > 0) {\n store.setMode('errorList');\n }\n } else if (mode === 'errorList') {\n if (key.escape) {\n store.setMode(isInteractive ? 'interactive' : 'normal');\n } else if (key.downArrow) {\n store.selectNextError();\n } else if (key.upArrow) {\n store.selectPrevError();\n } else if (key.return) {\n store.setMode('errorDetail');\n }\n } else if (mode === 'errorDetail') {\n if (key.escape) {\n store.setMode('errorList');\n } else if (key.downArrow) {\n store.selectNextError();\n } else if (key.upArrow) {\n store.selectPrevError();\n }\n }\n },\n { isActive: isRawModeSupported === true }\n );\n\n // Error list modal\n if (mode === 'errorList') {\n return <ErrorListModal errors={failedProcesses} selectedIndex={selectedErrorIndex} totalErrorLines={errorLineCount} />;\n }\n\n // Error detail modal\n if (mode === 'errorDetail') {\n const selectedError = store.getSelectedError();\n if (selectedError) {\n return <ErrorDetailModal error={selectedError} currentIndex={selectedErrorIndex} totalErrors={failedProcesses.length} />;\n }\n // Fallback if no error selected\n store.setMode('errorList');\n }\n\n // Normal/Interactive view - render in original registration order\n const showSelection = mode === 'interactive';\n return (\n <Box flexDirection=\"column\">\n {/* Header */}\n {header && (\n <>\n <Text>{header}</Text>\n <Divider />\n </>\n )}\n\n {/* All processes in registration order */}\n {processes.map((item, index) => (\n <Box key={item.id} flexDirection=\"column\">\n <CompactProcessLine item={item} isSelected={showSelection && index === selectedIndex} />\n {expandedId === item.id && <ExpandedOutput lines={item.lines} scrollOffset={scrollOffset} />}\n </Box>\n ))}\n\n {/* Status bar */}\n {showStatusBar && processes.length > 0 && (\n <>\n <Divider />\n <StatusBar running={runningCount} done={doneCount} errors={errorCount} errorLines={errorLineCount} />\n </>\n )}\n </Box>\n );\n}\n\n// Wrapper component that provides store context\nexport default function App({ store }: AppProps): React.JSX.Element {\n return (\n <StoreContext.Provider value={store}>\n <AppContent store={store} />\n </StoreContext.Provider>\n );\n}\n"],"names":["App","AppContent","store","exit","useApp","isRawModeSupported","useStdin","processes","useSyncExternalStore","subscribe","getSnapshot","shouldExit","getShouldExit","mode","getMode","selectedIndex","getSelectedIndex","selectedErrorIndex","getSelectedErrorIndex","expandedId","getExpandedId","scrollOffset","getScrollOffset","header","getHeader","showStatusBar","getShowStatusBar","isInteractive","getIsInteractive","failedProcesses","getFailedProcesses","runningCount","getRunningCount","doneCount","getDoneCount","errorCount","getErrorCount","errorLineCount","getErrorLineCount","isAllComplete","useEffect","setMode","useInput","input","key","escape","collapse","signalExit","return","toggleExpand","downArrow","scrollDown","EXPANDED_MAX_VISIBLE_LINES","selectNext","upArrow","scrollUp","selectPrev","selectNextError","selectPrevError","isActive","ErrorListModal","errors","totalErrorLines","selectedError","getSelectedError","ErrorDetailModal","error","currentIndex","totalErrors","length","showSelection","Box","flexDirection","Text","Divider","map","item","index","CompactProcessLine","isSelected","id","ExpandedOutput","lines","StatusBar","running","done","errorLines","StoreContext","Provider","value"],"mappings":"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"}
@@ -13,7 +13,7 @@ var _ink = require("ink");
13
13
  var _react = require("react");
14
14
  var _figurests = /*#__PURE__*/ _interop_require_default(require("../lib/figures.js"));
15
15
  var _formatts = require("../lib/format.js");
16
- var _processStorets = require("../state/processStore.js");
16
+ var _StoreContextts = require("../state/StoreContext.js");
17
17
  var _typests = require("../types.js");
18
18
  var _Spinnerts = /*#__PURE__*/ _interop_require_default(require("./Spinner.js"));
19
19
  function _define_property(obj, key, value) {
@@ -84,6 +84,7 @@ function getErrorCount(lines) {
84
84
  }
85
85
  var _default = /*#__PURE__*/ (0, _react.memo)(function CompactProcessLine(param) {
86
86
  var item = param.item, _param_isSelected = param.isSelected, isSelected = _param_isSelected === void 0 ? false : _param_isSelected;
87
+ var store = (0, _StoreContextts.useStore)();
87
88
  var stdout = (0, _ink.useStdout)().stdout;
88
89
  var terminalWidth = (stdout === null || stdout === void 0 ? void 0 : stdout.columns) || 80;
89
90
  var group = item.group, title = item.title, state = item.state, lines = item.lines;
@@ -92,7 +93,7 @@ var _default = /*#__PURE__*/ (0, _react.memo)(function CompactProcessLine(param)
92
93
  var displayName = group || title;
93
94
  // Calculate widths - use dynamic column width based on longest name
94
95
  var iconWidth = 2; // icon + space
95
- var maxGroupLength = _processStorets.processStore.getMaxGroupLength();
96
+ var maxGroupLength = store.getMaxGroupLength();
96
97
  var nameColumnWidth = (0, _formatts.calculateColumnWidth)('max', terminalWidth, maxGroupLength);
97
98
  var gap = 1; // space between name and status
98
99
  var statusWidth = terminalWidth - iconWidth - nameColumnWidth - gap;
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/components/CompactProcessLine.tsx"],"sourcesContent":["import { Box, Text, useStdout } from 'ink';\nimport { memo, useMemo } from 'react';\nimport figures from '../lib/figures.ts';\nimport { calculateColumnWidth } from '../lib/format.ts';\nimport { processStore } from '../state/processStore.ts';\nimport type { ChildProcess, Line } from '../types.ts';\nimport { LineType } from '../types.ts';\nimport Spinner from './Spinner.ts';\n\n// From: https://github.com/sindresorhus/cli-spinners/blob/00de8fbeee16fa49502fa4f687449f70f2c8ca2c/spinners.json#L2\nconst SPINNER = {\n interval: 80,\n frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],\n};\n\ntype Props = {\n item: ChildProcess;\n isSelected?: boolean;\n};\n\nfunction truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return `${str.slice(0, maxLength - 1)}…`;\n}\n\nfunction getLastOutputLine(lines: Line[]): string {\n for (let i = lines.length - 1; i >= 0; i--) {\n if (lines[i].text.length > 0) {\n return lines[i].text;\n }\n }\n return '';\n}\n\nfunction getErrorCount(lines: Line[]): number {\n return lines.filter((line) => line.type === LineType.stderr).length;\n}\n\nexport default memo(function CompactProcessLine({ item, isSelected = false }: Props) {\n const { stdout } = useStdout();\n const terminalWidth = stdout?.columns || 80;\n\n const { group, title, state, lines } = item;\n const selectionIndicator = isSelected ? figures.pointer : ' ';\n\n // Display name: prefer group, fall back to title\n const displayName = group || title;\n\n // Calculate widths - use dynamic column width based on longest name\n const iconWidth = 2; // icon + space\n const maxGroupLength = processStore.getMaxGroupLength();\n const nameColumnWidth = calculateColumnWidth('max', terminalWidth, maxGroupLength);\n const gap = 1; // space between name and status\n const statusWidth = terminalWidth - iconWidth - nameColumnWidth - gap;\n\n // Truncate name if needed and pad to column width\n const truncatedName = truncate(displayName, nameColumnWidth).padEnd(nameColumnWidth);\n\n // Status text based on state\n const statusText = useMemo(() => {\n if (state === 'running') {\n const lastLine = getLastOutputLine(lines);\n return lastLine ? truncate(lastLine, statusWidth) : '';\n }\n if (state === 'error') {\n const errorCount = getErrorCount(lines);\n return errorCount > 0 ? `${errorCount} error${errorCount > 1 ? 's' : ''}` : 'failed';\n }\n return ''; // success - no status text\n }, [state, lines, statusWidth]);\n\n // Icon based on state\n const icon = useMemo(() => {\n switch (state) {\n case 'running':\n return <Spinner {...SPINNER} />;\n case 'success':\n return <Text color=\"green\">{figures.tick}</Text>;\n case 'error':\n return <Text color=\"red\">{figures.cross}</Text>;\n }\n }, [state]);\n\n // Status text color\n const statusColor = state === 'error' ? 'red' : 'gray';\n\n return (\n <Box>\n <Text color={isSelected ? 'cyan' : undefined}>{selectionIndicator}</Text>\n <Box width={iconWidth}>{icon}</Box>\n <Text inverse={isSelected}>{truncatedName}</Text>\n {statusText && <Text color={statusColor}> {statusText}</Text>}\n </Box>\n );\n});\n"],"names":["SPINNER","interval","frames","truncate","str","maxLength","length","slice","getLastOutputLine","lines","i","text","getErrorCount","filter","line","type","LineType","stderr","memo","CompactProcessLine","item","isSelected","stdout","useStdout","terminalWidth","columns","group","title","state","selectionIndicator","figures","pointer","displayName","iconWidth","maxGroupLength","processStore","getMaxGroupLength","nameColumnWidth","calculateColumnWidth","gap","statusWidth","truncatedName","padEnd","statusText","useMemo","lastLine","errorCount","icon","Spinner","Text","color","tick","cross","statusColor","Box","undefined","width","inverse"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/components/CompactProcessLine.tsx"],"sourcesContent":["import { Box, Text, useStdout } from 'ink';\nimport { memo, useMemo } from 'react';\nimport figures from '../lib/figures.ts';\nimport { calculateColumnWidth } from '../lib/format.ts';\nimport { useStore } from '../state/StoreContext.ts';\nimport type { ChildProcess, Line } from '../types.ts';\nimport { LineType } from '../types.ts';\nimport Spinner from './Spinner.ts';\n\n// From: https://github.com/sindresorhus/cli-spinners/blob/00de8fbeee16fa49502fa4f687449f70f2c8ca2c/spinners.json#L2\nconst SPINNER = {\n interval: 80,\n frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],\n};\n\ntype Props = {\n item: ChildProcess;\n isSelected?: boolean;\n};\n\nfunction truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return `${str.slice(0, maxLength - 1)}…`;\n}\n\nfunction getLastOutputLine(lines: Line[]): string {\n for (let i = lines.length - 1; i >= 0; i--) {\n if (lines[i].text.length > 0) {\n return lines[i].text;\n }\n }\n return '';\n}\n\nfunction getErrorCount(lines: Line[]): number {\n return lines.filter((line) => line.type === LineType.stderr).length;\n}\n\nexport default memo(function CompactProcessLine({ item, isSelected = false }: Props) {\n const store = useStore();\n const { stdout } = useStdout();\n const terminalWidth = stdout?.columns || 80;\n\n const { group, title, state, lines } = item;\n const selectionIndicator = isSelected ? figures.pointer : ' ';\n\n // Display name: prefer group, fall back to title\n const displayName = group || title;\n\n // Calculate widths - use dynamic column width based on longest name\n const iconWidth = 2; // icon + space\n const maxGroupLength = store.getMaxGroupLength();\n const nameColumnWidth = calculateColumnWidth('max', terminalWidth, maxGroupLength);\n const gap = 1; // space between name and status\n const statusWidth = terminalWidth - iconWidth - nameColumnWidth - gap;\n\n // Truncate name if needed and pad to column width\n const truncatedName = truncate(displayName, nameColumnWidth).padEnd(nameColumnWidth);\n\n // Status text based on state\n const statusText = useMemo(() => {\n if (state === 'running') {\n const lastLine = getLastOutputLine(lines);\n return lastLine ? truncate(lastLine, statusWidth) : '';\n }\n if (state === 'error') {\n const errorCount = getErrorCount(lines);\n return errorCount > 0 ? `${errorCount} error${errorCount > 1 ? 's' : ''}` : 'failed';\n }\n return ''; // success - no status text\n }, [state, lines, statusWidth]);\n\n // Icon based on state\n const icon = useMemo(() => {\n switch (state) {\n case 'running':\n return <Spinner {...SPINNER} />;\n case 'success':\n return <Text color=\"green\">{figures.tick}</Text>;\n case 'error':\n return <Text color=\"red\">{figures.cross}</Text>;\n }\n }, [state]);\n\n // Status text color\n const statusColor = state === 'error' ? 'red' : 'gray';\n\n return (\n <Box>\n <Text color={isSelected ? 'cyan' : undefined}>{selectionIndicator}</Text>\n <Box width={iconWidth}>{icon}</Box>\n <Text inverse={isSelected}>{truncatedName}</Text>\n {statusText && <Text color={statusColor}> {statusText}</Text>}\n </Box>\n );\n});\n"],"names":["SPINNER","interval","frames","truncate","str","maxLength","length","slice","getLastOutputLine","lines","i","text","getErrorCount","filter","line","type","LineType","stderr","memo","CompactProcessLine","item","isSelected","store","useStore","stdout","useStdout","terminalWidth","columns","group","title","state","selectionIndicator","figures","pointer","displayName","iconWidth","maxGroupLength","getMaxGroupLength","nameColumnWidth","calculateColumnWidth","gap","statusWidth","truncatedName","padEnd","statusText","useMemo","lastLine","errorCount","icon","Spinner","Text","color","tick","cross","statusColor","Box","undefined","width","inverse"],"mappings":"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"}
@@ -9,8 +9,8 @@ function _export(target, all) {
9
9
  });
10
10
  }
11
11
  _export(exports, {
12
- get default () {
13
- return _default;
12
+ get createSession () {
13
+ return createSession;
14
14
  },
15
15
  get figures () {
16
16
  return _figurests.default;
@@ -40,5 +40,5 @@ function _interop_require_default(obj) {
40
40
  default: obj
41
41
  };
42
42
  }
43
- var _default = undefined;
43
+ var createSession = undefined;
44
44
  /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/index-cjs.ts"],"sourcesContent":["export { default as figures } from './lib/figures.ts';\nexport { default as formatArguments } from './lib/formatArguments.ts';\nexport * from './types.ts';\n\nimport type { default as spawnTerminal } from './spawnTerminal.ts';\nexport default undefined as typeof spawnTerminal;\n"],"names":["figures","formatArguments","undefined"],"mappings":";;;;;;;;;;;QAKA;eAAA;;QALoBA;eAAAA,kBAAO;;QACPC;eAAAA,0BAAe;;;gEADA;wEACQ;qBAC7B;;;;;;;;;;;;;;;;;;;IAGd,WAAeC"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/index-cjs.ts"],"sourcesContent":["export { default as figures } from './lib/figures.ts';\nexport { default as formatArguments } from './lib/formatArguments.ts';\nexport * from './types.ts';\n\nimport type { createSession as createSessionType, Session } from './session.ts';\nexport type { Session };\nexport const createSession = undefined as typeof createSessionType;\n"],"names":["createSession","figures","formatArguments","undefined"],"mappings":";;;;;;;;;;;QAMaA;eAAAA;;QANOC;eAAAA,kBAAO;;QACPC;eAAAA,0BAAe;;;gEADA;wEACQ;qBAC7B;;;;;;;;;;;;;;;;;;;AAIP,IAAMF,gBAAgBG"}
@@ -9,8 +9,8 @@ function _export(target, all) {
9
9
  });
10
10
  }
11
11
  _export(exports, {
12
- get default () {
13
- return _default;
12
+ get createSession () {
13
+ return createSession;
14
14
  },
15
15
  get figures () {
16
16
  return _figurests.default;
@@ -22,7 +22,7 @@ _export(exports, {
22
22
  var _figurests = /*#__PURE__*/ _interop_require_default(require("./lib/figures.js"));
23
23
  var _formatArgumentsts = /*#__PURE__*/ _interop_require_default(require("./lib/formatArguments.js"));
24
24
  _export_star(require("./types.js"), exports);
25
- var _spawnTerminalts = /*#__PURE__*/ _interop_require_default(require("./spawnTerminal.js"));
25
+ var _sessionts = require("./session.js");
26
26
  function _export_star(from, to) {
27
27
  Object.keys(from).forEach(function(k) {
28
28
  if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
@@ -42,5 +42,5 @@ function _interop_require_default(obj) {
42
42
  };
43
43
  }
44
44
  var major = +process.versions.node.split('.')[0];
45
- var _default = major > 18 ? _spawnTerminalts.default : undefined;
45
+ var createSession = major > 18 ? _sessionts.createSession : undefined;
46
46
  /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/index-esm.ts"],"sourcesContent":["export { default as figures } from './lib/figures.ts';\nexport { default as formatArguments } from './lib/formatArguments.ts';\nexport * from './types.ts';\n\nconst major = +process.versions.node.split('.')[0];\n\nimport { default as spawnTerminal } from './spawnTerminal.ts';\nexport default major > 18 ? spawnTerminal : (undefined as typeof spawnTerminal);\n"],"names":["figures","formatArguments","major","process","versions","node","split","spawnTerminal","undefined"],"mappings":";;;;;;;;;;;QAOA;eAAA;;QAPoBA;eAAAA,kBAAO;;QACPC;eAAAA,0BAAe;;;gEADA;wEACQ;qBAC7B;sEAI2B;;;;;;;;;;;;;;;;;;;AAFzC,IAAMC,QAAQ,CAACC,QAAQC,QAAQ,CAACC,IAAI,CAACC,KAAK,CAAC,IAAI,CAAC,EAAE;IAGlD,WAAeJ,QAAQ,KAAKK,wBAAa,GAAIC"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/index-esm.ts"],"sourcesContent":["export { default as figures } from './lib/figures.ts';\nexport { default as formatArguments } from './lib/formatArguments.ts';\nexport * from './types.ts';\n\nconst major = +process.versions.node.split('.')[0];\n\nimport { createSession as createSessionImpl, type Session } from './session.ts';\nexport type { Session };\nexport const createSession = major > 18 ? createSessionImpl : (undefined as typeof createSessionImpl);\n"],"names":["createSession","figures","formatArguments","major","process","versions","node","split","createSessionImpl","undefined"],"mappings":";;;;;;;;;;;QAQaA;eAAAA;;QAROC;eAAAA,kBAAO;;QACPC;eAAAA,0BAAe;;;gEADA;wEACQ;qBAC7B;yBAImD;;;;;;;;;;;;;;;;;;;AAFjE,IAAMC,QAAQ,CAACC,QAAQC,QAAQ,CAACC,IAAI,CAACC,KAAK,CAAC,IAAI,CAAC,EAAE;AAI3C,IAAMP,gBAAgBG,QAAQ,KAAKK,wBAAiB,GAAIC"}