spawn-term 2.1.0 → 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 +57 -44
  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 +54 -43
  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 -59
  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 -43
  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
@@ -0,0 +1,311 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "createSession", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return createSession;
9
+ }
10
+ });
11
+ var _jsxruntime = require("react/jsx-runtime");
12
+ var _crossspawncb = /*#__PURE__*/ _interop_require_wildcard(require("cross-spawn-cb"));
13
+ var _crypto = /*#__PURE__*/ _interop_require_default(require("crypto"));
14
+ var _ink = require("ink");
15
+ var _onone = /*#__PURE__*/ _interop_require_default(require("on-one"));
16
+ var _queuecb = /*#__PURE__*/ _interop_require_default(require("queue-cb"));
17
+ var _Appts = /*#__PURE__*/ _interop_require_default(require("./components/App.js"));
18
+ var _constantsts = require("./constants.js");
19
+ var _addLinests = /*#__PURE__*/ _interop_require_default(require("./lib/addLines.js"));
20
+ var _concatWritablets = /*#__PURE__*/ _interop_require_default(require("./lib/concatWritable.js"));
21
+ var _formatArgumentsts = /*#__PURE__*/ _interop_require_default(require("./lib/formatArguments.js"));
22
+ var _processStorets = require("./state/processStore.js");
23
+ var _typests = require("./types.js");
24
+ function _class_call_check(instance, Constructor) {
25
+ if (!(instance instanceof Constructor)) {
26
+ throw new TypeError("Cannot call a class as a function");
27
+ }
28
+ }
29
+ function _interop_require_default(obj) {
30
+ return obj && obj.__esModule ? obj : {
31
+ default: obj
32
+ };
33
+ }
34
+ function _getRequireWildcardCache(nodeInterop) {
35
+ if (typeof WeakMap !== "function") return null;
36
+ var cacheBabelInterop = new WeakMap();
37
+ var cacheNodeInterop = new WeakMap();
38
+ return (_getRequireWildcardCache = function(nodeInterop) {
39
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
40
+ })(nodeInterop);
41
+ }
42
+ function _interop_require_wildcard(obj, nodeInterop) {
43
+ if (!nodeInterop && obj && obj.__esModule) {
44
+ return obj;
45
+ }
46
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
47
+ return {
48
+ default: obj
49
+ };
50
+ }
51
+ var cache = _getRequireWildcardCache(nodeInterop);
52
+ if (cache && cache.has(obj)) {
53
+ return cache.get(obj);
54
+ }
55
+ var newObj = {
56
+ __proto__: null
57
+ };
58
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
59
+ for(var key in obj){
60
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
61
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
62
+ if (desc && (desc.get || desc.set)) {
63
+ Object.defineProperty(newObj, key, desc);
64
+ } else {
65
+ newObj[key] = obj[key];
66
+ }
67
+ }
68
+ }
69
+ newObj.default = obj;
70
+ if (cache) {
71
+ cache.set(obj, newObj);
72
+ }
73
+ return newObj;
74
+ }
75
+ function _object_without_properties(source, excluded) {
76
+ if (source == null) return {};
77
+ var target = _object_without_properties_loose(source, excluded);
78
+ var key, i;
79
+ if (Object.getOwnPropertySymbols) {
80
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
81
+ for(i = 0; i < sourceSymbolKeys.length; i++){
82
+ key = sourceSymbolKeys[i];
83
+ if (excluded.indexOf(key) >= 0) continue;
84
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
85
+ target[key] = source[key];
86
+ }
87
+ }
88
+ return target;
89
+ }
90
+ function _object_without_properties_loose(source, excluded) {
91
+ if (source == null) return {};
92
+ var target = {};
93
+ var sourceKeys = Object.keys(source);
94
+ var key, i;
95
+ for(i = 0; i < sourceKeys.length; i++){
96
+ key = sourceKeys[i];
97
+ if (excluded.indexOf(key) >= 0) continue;
98
+ target[key] = source[key];
99
+ }
100
+ return target;
101
+ }
102
+ var SessionImpl = /*#__PURE__*/ function() {
103
+ "use strict";
104
+ function SessionImpl() {
105
+ var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
106
+ _class_call_check(this, SessionImpl);
107
+ this.inkApp = null;
108
+ this.runningCount = 0;
109
+ this.closed = false;
110
+ this.waitCallbacks = [];
111
+ this.store = new _processStorets.ProcessStore(options);
112
+ // Render Ink app immediately
113
+ this.inkApp = (0, _ink.render)(/*#__PURE__*/ (0, _jsxruntime.jsx)(_Appts.default, {
114
+ store: this.store
115
+ }), {
116
+ incrementalRendering: true,
117
+ maxFps: _constantsts.DEFAULT_MAX_FPS
118
+ });
119
+ }
120
+ var _proto = SessionImpl.prototype;
121
+ _proto.spawn = function spawn(command, args, spawnOptions, options, callback) {
122
+ var _this = this;
123
+ if (this.closed) {
124
+ throw new Error('Session is closed');
125
+ }
126
+ var encoding = spawnOptions.encoding, stdio = spawnOptions.stdio, csOptions = _object_without_properties(spawnOptions, [
127
+ "encoding",
128
+ "stdio"
129
+ ]);
130
+ if (stdio === 'inherit') {
131
+ this.runningCount++;
132
+ var id = _crypto.default.randomUUID();
133
+ this.store.addProcess({
134
+ id: id,
135
+ title: [
136
+ command
137
+ ].concat((0, _formatArgumentsts.default)(args)).join(' '),
138
+ state: 'running',
139
+ lines: [],
140
+ group: options.group,
141
+ expanded: options.expanded
142
+ });
143
+ var cp = (0, _crossspawncb.crossSpawn)(command, args, csOptions);
144
+ var outputs = {
145
+ stdout: null,
146
+ stderr: null
147
+ };
148
+ var queue = new _queuecb.default();
149
+ if (cp.stdout) {
150
+ outputs.stdout = (0, _addLinests.default)(function(lines) {
151
+ _this.store.appendLines(id, lines.map(function(text) {
152
+ return {
153
+ type: _typests.LineType.stdout,
154
+ text: text
155
+ };
156
+ }));
157
+ });
158
+ queue.defer(_onone.default.bind(null, cp.stdout.pipe(outputs.stdout), [
159
+ 'error',
160
+ 'end',
161
+ 'close',
162
+ 'finish'
163
+ ]));
164
+ }
165
+ if (cp.stderr) {
166
+ outputs.stderr = (0, _addLinests.default)(function(lines) {
167
+ _this.store.appendLines(id, lines.map(function(text) {
168
+ return {
169
+ type: _typests.LineType.stderr,
170
+ text: text
171
+ };
172
+ }));
173
+ });
174
+ queue.defer(_onone.default.bind(null, cp.stderr.pipe(outputs.stderr), [
175
+ 'error',
176
+ 'end',
177
+ 'close',
178
+ 'finish'
179
+ ]));
180
+ }
181
+ queue.defer(_crossspawncb.default.worker.bind(null, cp, csOptions));
182
+ queue.await(function(err) {
183
+ var res = err ? err : {};
184
+ res.stdout = outputs.stdout ? outputs.stdout.output : null;
185
+ res.stderr = outputs.stderr ? outputs.stderr.output : null;
186
+ res.output = [
187
+ res.stdout,
188
+ res.stderr,
189
+ null
190
+ ];
191
+ _this.store.updateProcess(id, {
192
+ state: err ? 'error' : 'success'
193
+ });
194
+ _this.onProcessComplete();
195
+ err ? callback(err) : callback(null, res);
196
+ });
197
+ } else {
198
+ // Non-inherit mode: collect output but don't display in UI
199
+ var cp1 = (0, _crossspawncb.crossSpawn)(command, args, csOptions);
200
+ var outputs1 = {
201
+ stdout: null,
202
+ stderr: null
203
+ };
204
+ var queue1 = new _queuecb.default();
205
+ if (cp1.stdout) {
206
+ outputs1.stdout = (0, _concatWritablets.default)(function(output) {
207
+ outputs1.stdout.output = output.toString(encoding || 'utf8');
208
+ });
209
+ queue1.defer(_onone.default.bind(null, cp1.stdout.pipe(outputs1.stdout), [
210
+ 'error',
211
+ 'end',
212
+ 'close',
213
+ 'finish'
214
+ ]));
215
+ }
216
+ if (cp1.stderr) {
217
+ outputs1.stderr = (0, _concatWritablets.default)(function(output) {
218
+ outputs1.stderr.output = output.toString(encoding || 'utf8');
219
+ });
220
+ queue1.defer(_onone.default.bind(null, cp1.stderr.pipe(outputs1.stderr), [
221
+ 'error',
222
+ 'end',
223
+ 'close',
224
+ 'finish'
225
+ ]));
226
+ }
227
+ queue1.defer(_crossspawncb.default.worker.bind(null, cp1, csOptions));
228
+ queue1.await(function(err) {
229
+ var res = err ? err : {};
230
+ res.stdout = outputs1.stdout ? outputs1.stdout.output : null;
231
+ res.stderr = outputs1.stderr ? outputs1.stderr.output : null;
232
+ res.output = [
233
+ res.stdout,
234
+ res.stderr,
235
+ null
236
+ ];
237
+ err ? callback(err) : callback(null, res);
238
+ });
239
+ }
240
+ };
241
+ _proto.close = function close() {
242
+ if (this.closed) return;
243
+ this.closed = true;
244
+ this.cleanup();
245
+ };
246
+ _proto.waitAndClose = function waitAndClose(callback) {
247
+ if (this.closed) {
248
+ callback === null || callback === void 0 ? void 0 : callback();
249
+ return;
250
+ }
251
+ if (this.runningCount === 0) {
252
+ this.close();
253
+ callback === null || callback === void 0 ? void 0 : callback();
254
+ } else {
255
+ if (callback) this.waitCallbacks.push(callback);
256
+ // Will close when runningCount hits 0
257
+ }
258
+ };
259
+ _proto.onProcessComplete = function onProcessComplete() {
260
+ this.runningCount--;
261
+ if (this.runningCount === 0 && this.waitCallbacks.length > 0) {
262
+ this.close();
263
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
264
+ try {
265
+ for(var _iterator = this.waitCallbacks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
266
+ var cb = _step.value;
267
+ cb();
268
+ }
269
+ } catch (err) {
270
+ _didIteratorError = true;
271
+ _iteratorError = err;
272
+ } finally{
273
+ try {
274
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
275
+ _iterator.return();
276
+ }
277
+ } finally{
278
+ if (_didIteratorError) {
279
+ throw _iteratorError;
280
+ }
281
+ }
282
+ }
283
+ this.waitCallbacks = [];
284
+ }
285
+ };
286
+ _proto.cleanup = function cleanup() {
287
+ var _this = this;
288
+ // Signal exit to React component
289
+ this.store.signalExit(function() {
290
+ _this.store.reset();
291
+ process.stdout.write('\x1b[?25h'); // show cursor
292
+ });
293
+ // Wait for Ink to finish
294
+ if (this.inkApp) {
295
+ this.inkApp.waitUntilExit().then(function() {
296
+ var cb = _this.store.getExitCallback();
297
+ cb === null || cb === void 0 ? void 0 : cb();
298
+ }).catch(function() {
299
+ var cb = _this.store.getExitCallback();
300
+ cb === null || cb === void 0 ? void 0 : cb();
301
+ });
302
+ this.inkApp = null;
303
+ }
304
+ };
305
+ return SessionImpl;
306
+ }();
307
+ function createSession() {
308
+ var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
309
+ return new SessionImpl(options);
310
+ }
311
+ /* 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; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/session.tsx"],"sourcesContent":["import spawn, { crossSpawn, type SpawnResult } from 'cross-spawn-cb';\nimport crypto from 'crypto';\nimport { render } from 'ink';\nimport oo from 'on-one';\nimport Queue from 'queue-cb';\n\nimport App from './components/App.ts';\nimport { DEFAULT_MAX_FPS } from './constants.ts';\nimport addLines from './lib/addLines.ts';\nimport concatWritable from './lib/concatWritable.ts';\nimport formatArguments from './lib/formatArguments.ts';\nimport { ProcessStore } from './state/processStore.ts';\nimport type { ProcessOptions, SessionOptions, SpawnError, SpawnOptions, TerminalCallback } from './types.ts';\nimport { LineType } from './types.ts';\n\nexport interface Session {\n spawn(command: string, args: string[], spawnOptions: SpawnOptions, options: ProcessOptions, callback: TerminalCallback): void;\n close(): void;\n waitAndClose(callback?: () => void): void;\n}\n\nclass SessionImpl implements Session {\n private store: ProcessStore;\n private inkApp: ReturnType<typeof render> | null = null;\n private runningCount = 0;\n private closed = false;\n private waitCallbacks: (() => void)[] = [];\n\n constructor(options: SessionOptions = {}) {\n this.store = new ProcessStore(options);\n\n // Render Ink app immediately\n this.inkApp = render(<App store={this.store} />, {\n incrementalRendering: true,\n maxFps: DEFAULT_MAX_FPS,\n });\n }\n\n spawn(command: string, args: string[], spawnOptions: SpawnOptions, options: ProcessOptions, callback: TerminalCallback): void {\n if (this.closed) {\n throw new Error('Session is closed');\n }\n\n const { encoding, stdio, ...csOptions } = spawnOptions;\n\n if (stdio === 'inherit') {\n this.runningCount++;\n const id = crypto.randomUUID();\n this.store.addProcess({\n id,\n title: [command].concat(formatArguments(args)).join(' '),\n state: 'running',\n lines: [],\n group: options.group,\n expanded: options.expanded,\n });\n\n const cp = crossSpawn(command, args, csOptions);\n const outputs = { stdout: null as ReturnType<typeof addLines> | null, stderr: null as ReturnType<typeof addLines> | null };\n\n const queue = new Queue();\n if (cp.stdout) {\n outputs.stdout = addLines((lines) => {\n this.store.appendLines(\n id,\n lines.map((text) => ({ type: LineType.stdout, text }))\n );\n });\n queue.defer(oo.bind(null, cp.stdout.pipe(outputs.stdout), ['error', 'end', 'close', 'finish']));\n }\n if (cp.stderr) {\n outputs.stderr = addLines((lines) => {\n this.store.appendLines(\n id,\n lines.map((text) => ({ type: LineType.stderr, text }))\n );\n });\n queue.defer(oo.bind(null, cp.stderr.pipe(outputs.stderr), ['error', 'end', 'close', 'finish']));\n }\n queue.defer(spawn.worker.bind(null, cp, csOptions));\n queue.await((err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = outputs.stdout ? (outputs.stdout as unknown as { output: string }).output : null;\n res.stderr = outputs.stderr ? (outputs.stderr as unknown as { output: string }).output : null;\n res.output = [res.stdout, res.stderr, null];\n this.store.updateProcess(id, { state: err ? 'error' : 'success' });\n\n this.onProcessComplete();\n err ? callback(err) : callback(null, res);\n });\n } else {\n // Non-inherit mode: collect output but don't display in UI\n const cp = crossSpawn(command, args, csOptions);\n const outputs = { stdout: null as ReturnType<typeof concatWritable> | null, stderr: null as ReturnType<typeof concatWritable> | null };\n\n const queue = new Queue();\n if (cp.stdout) {\n outputs.stdout = concatWritable((output) => {\n (outputs.stdout as unknown as { output: string }).output = output.toString(encoding || 'utf8');\n });\n queue.defer(oo.bind(null, cp.stdout.pipe(outputs.stdout), ['error', 'end', 'close', 'finish']));\n }\n if (cp.stderr) {\n outputs.stderr = concatWritable((output) => {\n (outputs.stderr as unknown as { output: string }).output = output.toString(encoding || 'utf8');\n });\n queue.defer(oo.bind(null, cp.stderr.pipe(outputs.stderr), ['error', 'end', 'close', 'finish']));\n }\n queue.defer(spawn.worker.bind(null, cp, csOptions));\n queue.await((err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = outputs.stdout ? (outputs.stdout as unknown as { output: string }).output : null;\n res.stderr = outputs.stderr ? (outputs.stderr as unknown as { output: string }).output : null;\n res.output = [res.stdout, res.stderr, null];\n err ? callback(err) : callback(null, res);\n });\n }\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n this.cleanup();\n }\n\n waitAndClose(callback?: () => void): void {\n if (this.closed) {\n callback?.();\n return;\n }\n\n if (this.runningCount === 0) {\n this.close();\n callback?.();\n } else {\n if (callback) this.waitCallbacks.push(callback);\n // Will close when runningCount hits 0\n }\n }\n\n private onProcessComplete(): void {\n this.runningCount--;\n if (this.runningCount === 0 && this.waitCallbacks.length > 0) {\n this.close();\n for (const cb of this.waitCallbacks) cb();\n this.waitCallbacks = [];\n }\n }\n\n private cleanup(): void {\n // Signal exit to React component\n this.store.signalExit(() => {\n this.store.reset();\n process.stdout.write('\\x1b[?25h'); // show cursor\n });\n\n // Wait for Ink to finish\n if (this.inkApp) {\n this.inkApp\n .waitUntilExit()\n .then(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n })\n .catch(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n });\n this.inkApp = null;\n }\n }\n}\n\nexport function createSession(options: SessionOptions = {}): Session {\n return new SessionImpl(options);\n}\n"],"names":["createSession","SessionImpl","options","inkApp","runningCount","closed","waitCallbacks","store","ProcessStore","render","App","incrementalRendering","maxFps","DEFAULT_MAX_FPS","spawn","command","args","spawnOptions","callback","Error","encoding","stdio","csOptions","id","crypto","randomUUID","addProcess","title","concat","formatArguments","join","state","lines","group","expanded","cp","crossSpawn","outputs","stdout","stderr","queue","Queue","addLines","appendLines","map","text","type","LineType","defer","oo","bind","pipe","worker","await","err","res","output","updateProcess","onProcessComplete","concatWritable","toString","close","cleanup","waitAndClose","push","length","cb","signalExit","reset","process","write","waitUntilExit","then","getExitCallback","catch"],"mappings":"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"}
@@ -1 +1,6 @@
1
- export default function App(): React.JSX.Element;
1
+ import type { ProcessStore } from '../state/processStore.js';
2
+ interface AppProps {
3
+ store: ProcessStore;
4
+ }
5
+ export default function App({ store }: AppProps): React.JSX.Element;
6
+ export {};
@@ -1,6 +1,6 @@
1
1
  export { default as figures } from './lib/figures.js';
2
2
  export { default as formatArguments } from './lib/formatArguments.js';
3
3
  export * from './types.js';
4
- import type { default as spawnTerminal } from './spawnTerminal.js';
5
- declare const _default: typeof spawnTerminal;
6
- export default _default;
4
+ import type { createSession as createSessionType, Session } from './session.js';
5
+ export type { Session };
6
+ export declare const createSession: typeof createSessionType;
@@ -1,6 +1,6 @@
1
1
  export { default as figures } from './lib/figures.js';
2
2
  export { default as formatArguments } from './lib/formatArguments.js';
3
3
  export * from './types.js';
4
- import { default as spawnTerminal } from './spawnTerminal.js';
5
- declare const _default: typeof spawnTerminal;
6
- export default _default;
4
+ import { createSession as createSessionImpl, type Session } from './session.js';
5
+ export type { Session };
6
+ export declare const createSession: typeof createSessionImpl;
@@ -0,0 +1,7 @@
1
+ import type { ProcessOptions, SessionOptions, SpawnOptions, TerminalCallback } from './types.js';
2
+ export interface Session {
3
+ spawn(command: string, args: string[], spawnOptions: SpawnOptions, options: ProcessOptions, callback: TerminalCallback): void;
4
+ close(): void;
5
+ waitAndClose(callback?: () => void): void;
6
+ }
7
+ export declare function createSession(options?: SessionOptions): Session;
@@ -0,0 +1,3 @@
1
+ import type { ProcessStore } from './processStore.js';
2
+ export declare const StoreContext: import("react").Context<ProcessStore>;
3
+ export declare function useStore(): ProcessStore;
@@ -1,7 +1,7 @@
1
- import type { ChildProcess, Line } from '../types.js';
1
+ import type { ChildProcess, Line, SessionOptions } from '../types.js';
2
2
  type Listener = () => void;
3
3
  type Mode = 'normal' | 'interactive' | 'errorList' | 'errorDetail';
4
- declare class ProcessStore {
4
+ export declare class ProcessStore {
5
5
  private processes;
6
6
  private completedIds;
7
7
  private listeners;
@@ -13,6 +13,9 @@ declare class ProcessStore {
13
13
  private expandedId;
14
14
  private scrollOffset;
15
15
  private header;
16
+ private showStatusBar;
17
+ private isInteractive;
18
+ constructor(options?: SessionOptions);
16
19
  subscribe: (listener: Listener) => (() => void);
17
20
  getSnapshot: () => ChildProcess[];
18
21
  getRunningProcesses: () => ChildProcess[];
@@ -53,5 +56,4 @@ declare class ProcessStore {
53
56
  reset(): void;
54
57
  private notify;
55
58
  }
56
- export declare const processStore: ProcessStore;
57
- export type { ProcessStore };
59
+ export {};
@@ -1,12 +1,14 @@
1
1
  export type { SpawnCallback, SpawnError, SpawnOptions, SpawnResult } from 'cross-spawn-cb';
2
2
  import type { SpawnError, SpawnResult } from 'cross-spawn-cb';
3
- export type TerminalOptions = {
4
- group?: string;
5
- expanded?: boolean;
3
+ export type SessionOptions = {
6
4
  header?: string;
7
5
  showStatusBar?: boolean;
8
6
  interactive?: boolean;
9
7
  };
8
+ export type ProcessOptions = {
9
+ group?: string;
10
+ expanded?: boolean;
11
+ };
10
12
  export type TerminalCallback = (error?: SpawnError, result?: SpawnResult) => undefined;
11
13
  export declare const LineType: {
12
14
  readonly stdout: 1;
@@ -24,7 +26,4 @@ export type ChildProcess = {
24
26
  state: State;
25
27
  lines: Line[];
26
28
  expanded?: boolean;
27
- header?: string;
28
- showStatusBar?: boolean;
29
- interactive?: boolean;
30
29
  };
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get StoreContext () {
13
+ return StoreContext;
14
+ },
15
+ get useStore () {
16
+ return useStore;
17
+ }
18
+ });
19
+ var _react = require("react");
20
+ var StoreContext = /*#__PURE__*/ (0, _react.createContext)(null);
21
+ function useStore() {
22
+ var store = (0, _react.useContext)(StoreContext);
23
+ if (!store) {
24
+ throw new Error('useStore must be used within a StoreContext.Provider');
25
+ }
26
+ return store;
27
+ }
28
+ /* 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; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/state/StoreContext.tsx"],"sourcesContent":["import { createContext, useContext } from 'react';\nimport type { ProcessStore } from './processStore.ts';\n\nexport const StoreContext = createContext<ProcessStore | null>(null);\n\nexport function useStore(): ProcessStore {\n const store = useContext(StoreContext);\n if (!store) {\n throw new Error('useStore must be used within a StoreContext.Provider');\n }\n return store;\n}\n"],"names":["StoreContext","useStore","createContext","store","useContext","Error"],"mappings":";;;;;;;;;;;QAGaA;eAAAA;;QAEGC;eAAAA;;;qBAL0B;AAGnC,IAAMD,6BAAeE,IAAAA,oBAAa,EAAsB;AAExD,SAASD;IACd,IAAME,QAAQC,IAAAA,iBAAU,EAACJ;IACzB,IAAI,CAACG,OAAO;QACV,MAAM,IAAIE,MAAM;IAClB;IACA,OAAOF;AACT"}
@@ -2,10 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, "processStore", {
5
+ Object.defineProperty(exports, "ProcessStore", {
6
6
  enumerable: true,
7
7
  get: function() {
8
- return processStore;
8
+ return ProcessStore;
9
9
  }
10
10
  });
11
11
  var _constantsts = require("../constants.js");
@@ -72,6 +72,7 @@ var ProcessStore = /*#__PURE__*/ function() {
72
72
  "use strict";
73
73
  function ProcessStore() {
74
74
  var _this = this;
75
+ var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
75
76
  _class_call_check(this, ProcessStore);
76
77
  this.processes = [];
77
78
  this.completedIds = []; // Track completion order
@@ -84,6 +85,8 @@ var ProcessStore = /*#__PURE__*/ function() {
84
85
  this.selectedErrorIndex = 0;
85
86
  this.expandedId = null;
86
87
  this.scrollOffset = 0;
88
+ this.showStatusBar = false;
89
+ this.isInteractive = false;
87
90
  // useSyncExternalStore API
88
91
  this.subscribe = function(listener) {
89
92
  _this.listeners.add(listener);
@@ -163,21 +166,15 @@ var ProcessStore = /*#__PURE__*/ function() {
163
166
  this.getScrollOffset = function() {
164
167
  return _this.scrollOffset;
165
168
  };
166
- // Get header
169
+ // Session-level getters (set at session creation, immutable)
167
170
  this.getHeader = function() {
168
171
  return _this.header;
169
172
  };
170
- // Show status bar only if any process sets showStatusBar: true (default: false)
171
173
  this.getShowStatusBar = function() {
172
- return _this.processes.some(function(p) {
173
- return p.showStatusBar === true;
174
- });
174
+ return _this.showStatusBar;
175
175
  };
176
- // Interactive mode if any process has interactive: true
177
176
  this.getIsInteractive = function() {
178
- return _this.processes.some(function(p) {
179
- return p.interactive === true;
180
- });
177
+ return _this.isInteractive;
181
178
  };
182
179
  this.isAllComplete = function() {
183
180
  return _this.processes.length > 0 && _this.processes.every(function(p) {
@@ -190,14 +187,15 @@ var ProcessStore = /*#__PURE__*/ function() {
190
187
  this.getExitCallback = function() {
191
188
  return _this.exitCallback;
192
189
  };
190
+ this.header = options.header;
191
+ var _options_showStatusBar;
192
+ this.showStatusBar = (_options_showStatusBar = options.showStatusBar) !== null && _options_showStatusBar !== void 0 ? _options_showStatusBar : false;
193
+ var _options_interactive;
194
+ this.isInteractive = (_options_interactive = options.interactive) !== null && _options_interactive !== void 0 ? _options_interactive : false;
193
195
  }
194
196
  var _proto = ProcessStore.prototype;
195
197
  // Mutations - Ink handles render throttling at 30 FPS
196
198
  _proto.addProcess = function addProcess(process) {
197
- // Set header on first process that provides one
198
- if (this.header === undefined && process.header !== undefined) {
199
- this.header = process.header;
200
- }
201
199
  this.processes = _to_consumable_array(this.processes).concat([
202
200
  process
203
201
  ]);
@@ -340,6 +338,6 @@ var ProcessStore = /*#__PURE__*/ function() {
340
338
  });
341
339
  };
342
340
  return ProcessStore;
343
- }();
344
- var processStore = new ProcessStore();
341
+ } // Note: No global singleton - session creates its own store instance
342
+ ();
345
343
  /* 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/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":["processStore","ProcessStore","processes","completedIds","listeners","Set","shouldExit","exitCallback","mode","selectedIndex","selectedErrorIndex","expandedId","scrollOffset","subscribe","listener","add","delete","getSnapshot","getRunningProcesses","filter","p","state","getCompletedProcesses","map","id","find","undefined","getFailedProcesses","getRunningCount","length","getMaxGroupLength","Math","DEFAULT_COLUMN_WIDTH","max","group","title","getDoneCount","getErrorCount","getErrorLineCount","reduce","total","lines","l","type","LineType","stderr","getMode","getSelectedIndex","getSelectedErrorIndex","getExpandedId","getScrollOffset","getHeader","header","getShowStatusBar","some","showStatusBar","getIsInteractive","interactive","isAllComplete","every","getShouldExit","getExitCallback","addProcess","process","notify","updateProcess","update","oldProcess","wasRunning","isNowComplete","includes","appendLines","newLines","concat","getProcess","setMode","selectNext","selectPrev","getSelectedProcess","selectNextError","failed","selectPrevError","getSelectedError","toggleExpand","selected","collapse","scrollDown","maxVisible","maxOffset","scrollUp","signalExit","callback","reset","forEach"],"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, SessionOptions } from '../types.ts';\nimport { LineType } from '../types.ts';\n\ntype Listener = () => void;\ntype Mode = 'normal' | 'interactive' | 'errorList' | 'errorDetail';\n\nexport class 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 // Session-level display settings (set once at session creation)\n private header: string | undefined;\n private showStatusBar = false;\n private isInteractive = false;\n\n constructor(options: SessionOptions = {}) {\n this.header = options.header;\n this.showStatusBar = options.showStatusBar ?? false;\n this.isInteractive = options.interactive ?? false;\n }\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 // Session-level getters (set at session creation, immutable)\n getHeader = (): string | undefined => this.header;\n getShowStatusBar = (): boolean => this.showStatusBar;\n getIsInteractive = (): boolean => this.isInteractive;\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 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\n// Note: No global singleton - session creates its own store instance\n"],"names":["ProcessStore","options","processes","completedIds","listeners","Set","shouldExit","exitCallback","mode","selectedIndex","selectedErrorIndex","expandedId","scrollOffset","showStatusBar","isInteractive","subscribe","listener","add","delete","getSnapshot","getRunningProcesses","filter","p","state","getCompletedProcesses","map","id","find","undefined","getFailedProcesses","getRunningCount","length","getMaxGroupLength","Math","DEFAULT_COLUMN_WIDTH","max","group","title","getDoneCount","getErrorCount","getErrorLineCount","reduce","total","lines","l","type","LineType","stderr","getMode","getSelectedIndex","getSelectedErrorIndex","getExpandedId","getScrollOffset","getHeader","header","getShowStatusBar","getIsInteractive","isAllComplete","every","getShouldExit","getExitCallback","interactive","addProcess","process","notify","updateProcess","update","oldProcess","wasRunning","isNowComplete","includes","appendLines","newLines","concat","getProcess","setMode","selectNext","selectPrev","getSelectedProcess","selectNextError","failed","selectPrevError","getSelectedError","toggleExpand","selected","collapse","scrollDown","maxVisible","maxOffset","scrollUp","signalExit","callback","reset","forEach"],"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 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":";;;;+BAcaA;;;eAAAA;;;AAAN,IAAMA,WAAW;IACtBC,QAAQ;IACRC,QAAQ;AACV"}
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\n// Session-level options (set at session creation, immutable)\nexport type SessionOptions = {\n header?: string;\n showStatusBar?: boolean;\n interactive?: boolean;\n};\n\n// Per-process options (set when spawning each process)\nexport type ProcessOptions = {\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';\n\n// Internal representation of a child process\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":";;;;+BAmBaA;;;eAAAA;;;AAAN,IAAMA,WAAW;IACtBC,QAAQ;IACRC,QAAQ;AACV"}