spawn-term 3.1.2 → 3.1.4

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 (39) hide show
  1. package/dist/cjs/compat.js +25 -3
  2. package/dist/cjs/compat.js.map +1 -1
  3. package/dist/cjs/components/App.js +58 -19
  4. package/dist/cjs/components/App.js.map +1 -1
  5. package/dist/cjs/components/ErrorFooter.js +2 -10
  6. package/dist/cjs/components/ErrorFooter.js.map +1 -1
  7. package/dist/cjs/index-cjs.js.map +1 -1
  8. package/dist/cjs/index-esm.js.map +1 -1
  9. package/dist/cjs/src/compat.d.ts +1 -0
  10. package/dist/cjs/src/index-cjs.d.ts +1 -0
  11. package/dist/cjs/src/index-esm.d.ts +1 -0
  12. package/dist/cjs/src/state/Navigator.d.ts +27 -0
  13. package/dist/cjs/src/state/processStore.d.ts +28 -25
  14. package/dist/cjs/src/types.d.ts +3 -0
  15. package/dist/cjs/state/Navigator.js +127 -0
  16. package/dist/cjs/state/Navigator.js.map +1 -0
  17. package/dist/cjs/state/processStore.js +196 -109
  18. package/dist/cjs/state/processStore.js.map +1 -1
  19. package/dist/cjs/types.js.map +1 -1
  20. package/dist/esm/compat.js +14 -0
  21. package/dist/esm/compat.js.map +1 -1
  22. package/dist/esm/components/App.js +58 -19
  23. package/dist/esm/components/App.js.map +1 -1
  24. package/dist/esm/components/ErrorFooter.js +2 -10
  25. package/dist/esm/components/ErrorFooter.js.map +1 -1
  26. package/dist/esm/index-cjs.js.map +1 -1
  27. package/dist/esm/index-esm.js.map +1 -1
  28. package/dist/esm/src/compat.d.ts +1 -0
  29. package/dist/esm/src/index-cjs.d.ts +1 -0
  30. package/dist/esm/src/index-esm.d.ts +1 -0
  31. package/dist/esm/src/state/Navigator.d.ts +27 -0
  32. package/dist/esm/src/state/processStore.d.ts +28 -25
  33. package/dist/esm/src/types.d.ts +3 -0
  34. package/dist/esm/state/Navigator.js +114 -0
  35. package/dist/esm/state/Navigator.js.map +1 -0
  36. package/dist/esm/state/processStore.js +161 -104
  37. package/dist/esm/state/processStore.js.map +1 -1
  38. package/dist/esm/types.js.map +1 -1
  39. package/package.json +1 -1
@@ -8,8 +8,10 @@ Object.defineProperty(exports, "ProcessStore", {
8
8
  return ProcessStore;
9
9
  }
10
10
  });
11
+ var _compatts = require("../compat.js");
11
12
  var _constantsts = require("../constants.js");
12
13
  var _typests = require("../types.js");
14
+ var _Navigatorts = require("./Navigator.js");
13
15
  function _array_like_to_array(arr, len) {
14
16
  if (len == null || len > arr.length) len = arr.length;
15
17
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
@@ -57,6 +59,30 @@ function _object_spread(target) {
57
59
  }
58
60
  return target;
59
61
  }
62
+ function ownKeys(object, enumerableOnly) {
63
+ var keys = Object.keys(object);
64
+ if (Object.getOwnPropertySymbols) {
65
+ var symbols = Object.getOwnPropertySymbols(object);
66
+ if (enumerableOnly) {
67
+ symbols = symbols.filter(function(sym) {
68
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
69
+ });
70
+ }
71
+ keys.push.apply(keys, symbols);
72
+ }
73
+ return keys;
74
+ }
75
+ function _object_spread_props(target, source) {
76
+ source = source != null ? source : {};
77
+ if (Object.getOwnPropertyDescriptors) {
78
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
79
+ } else {
80
+ ownKeys(Object(source)).forEach(function(key) {
81
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
82
+ });
83
+ }
84
+ return target;
85
+ }
60
86
  function _to_consumable_array(arr) {
61
87
  return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
62
88
  }
@@ -74,22 +100,21 @@ var ProcessStore = /*#__PURE__*/ function() {
74
100
  var _this = this;
75
101
  var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
76
102
  _class_call_check(this, ProcessStore);
103
+ // === DATA: Process collection ===
77
104
  this.processes = [];
78
105
  this.completedIds = []; // Track completion order
79
- this.listeners = new Set();
80
- this.shouldExit = false;
81
- this.exitCallback = null;
82
- // UI state
106
+ // === VIEW STATE ===
83
107
  this.mode = 'normal';
84
- this.selectedIndex = 0;
85
108
  this.expandedId = null;
86
- this.scrollOffset = 0;
87
- this.listScrollOffset = 0; // Viewport offset for process list
88
109
  this.errorFooterExpanded = false; // For non-interactive error footer
89
- this.bufferVersion = 0; // Increments on every notify() to trigger re-renders
90
110
  this.showStatusBar = false;
91
111
  this.isInteractive = false;
92
- // useSyncExternalStore API
112
+ // === INFRASTRUCTURE ===
113
+ this.listeners = new Set();
114
+ this.shouldExit = false;
115
+ this.exitCallback = null;
116
+ this.bufferVersion = 0; // Increments on every notify() to trigger re-renders
117
+ // === SUBSCRIPTION API (useSyncExternalStore) ===
93
118
  this.subscribe = function(listener) {
94
119
  _this.listeners.add(listener);
95
120
  return function() {
@@ -99,7 +124,7 @@ var ProcessStore = /*#__PURE__*/ function() {
99
124
  this.getSnapshot = function() {
100
125
  return _this.processes;
101
126
  };
102
- // Filtered getters
127
+ // === DATA: Queries ===
103
128
  this.getRunningProcesses = function() {
104
129
  return _this.processes.filter(function(p) {
105
130
  return p.state === 'running';
@@ -108,7 +133,7 @@ var ProcessStore = /*#__PURE__*/ function() {
108
133
  this.getCompletedProcesses = function() {
109
134
  // Return in completion order
110
135
  return _this.completedIds.map(function(id) {
111
- return _this.processes.find(function(p) {
136
+ return (0, _compatts.arrayFind)(_this.processes, function(p) {
112
137
  return p.id === id;
113
138
  });
114
139
  }).filter(function(p) {
@@ -150,21 +175,18 @@ var ProcessStore = /*#__PURE__*/ function() {
150
175
  return total + _this.getProcessLineCount(p.id);
151
176
  }, 0);
152
177
  };
153
- // UI state getters
178
+ // === VIEW STATE: Getters ===
154
179
  this.getMode = function() {
155
180
  return _this.mode;
156
181
  };
157
182
  this.getSelectedIndex = function() {
158
- return _this.selectedIndex;
183
+ return _this.listNav.position;
159
184
  };
160
185
  this.getExpandedId = function() {
161
186
  return _this.expandedId;
162
187
  };
163
- this.getScrollOffset = function() {
164
- return _this.scrollOffset;
165
- };
166
188
  this.getListScrollOffset = function() {
167
- return _this.listScrollOffset;
189
+ return _this.listNav.viewportOffset;
168
190
  };
169
191
  this.getErrorFooterExpanded = function() {
170
192
  return _this.errorFooterExpanded;
@@ -172,6 +194,14 @@ var ProcessStore = /*#__PURE__*/ function() {
172
194
  this.getBufferVersion = function() {
173
195
  return _this.bufferVersion;
174
196
  };
197
+ // Get scroll offset for expanded process (or 0 if none)
198
+ this.getScrollOffset = function() {
199
+ var _process_scrollNav;
200
+ if (!_this.expandedId) return 0;
201
+ var process = _this.getProcess(_this.expandedId);
202
+ var _process_scrollNav_position;
203
+ return (_process_scrollNav_position = process === null || process === void 0 ? void 0 : (_process_scrollNav = process.scrollNav) === null || _process_scrollNav === void 0 ? void 0 : _process_scrollNav.position) !== null && _process_scrollNav_position !== void 0 ? _process_scrollNav_position : 0;
204
+ };
175
205
  // Session-level getters (set at session creation, immutable)
176
206
  this.getHeader = function() {
177
207
  return _this.header;
@@ -198,17 +228,49 @@ var ProcessStore = /*#__PURE__*/ function() {
198
228
  this.showStatusBar = (_options_showStatusBar = options.showStatusBar) !== null && _options_showStatusBar !== void 0 ? _options_showStatusBar : false;
199
229
  var _options_interactive;
200
230
  this.isInteractive = (_options_interactive = options.interactive) !== null && _options_interactive !== void 0 ? _options_interactive : false;
231
+ // Create list navigator with wrap-around behavior
232
+ this.listNav = (0, _Navigatorts.createNavigator)({
233
+ getLength: function() {
234
+ return _this.processes.length;
235
+ },
236
+ wrap: true,
237
+ onMove: function() {
238
+ return _this.notify();
239
+ }
240
+ });
201
241
  }
202
242
  var _proto = ProcessStore.prototype;
203
- // Mutations - Ink handles render throttling at 30 FPS
243
+ _proto.getErrorLines = function getErrorLines() {
244
+ var _this = this;
245
+ return this.getFailedProcesses().map(function(p) {
246
+ return {
247
+ processName: p.group || p.title,
248
+ lines: _this.getProcessLines(p.id)
249
+ };
250
+ });
251
+ };
252
+ // === DATA: Mutations ===
204
253
  _proto.addProcess = function addProcess(process) {
254
+ var _this = this;
255
+ // Create scroll navigator for this process
256
+ var processWithNav = _object_spread_props(_object_spread({}, process), {
257
+ scrollNav: (0, _Navigatorts.createNavigator)({
258
+ getLength: function() {
259
+ return _this.getProcessLineCount(processWithNav.id);
260
+ },
261
+ wrap: false,
262
+ onMove: function() {
263
+ return _this.notify();
264
+ }
265
+ })
266
+ });
205
267
  this.processes = _to_consumable_array(this.processes).concat([
206
- process
268
+ processWithNav
207
269
  ]);
208
270
  this.notify();
209
271
  };
210
272
  _proto.updateProcess = function updateProcess(id, update) {
211
- var oldProcess = this.processes.find(function(p) {
273
+ var oldProcess = (0, _compatts.arrayFind)(this.processes, function(p) {
212
274
  return p.id === id;
213
275
  });
214
276
  var wasRunning = (oldProcess === null || oldProcess === void 0 ? void 0 : oldProcess.state) === 'running';
@@ -229,7 +291,7 @@ var ProcessStore = /*#__PURE__*/ function() {
229
291
  this.notify();
230
292
  };
231
293
  _proto.appendLines = function appendLines(id, newLines) {
232
- var process = this.processes.find(function(p) {
294
+ var process = (0, _compatts.arrayFind)(this.processes, function(p) {
233
295
  return p.id === id;
234
296
  });
235
297
  if (process) {
@@ -239,7 +301,7 @@ var ProcessStore = /*#__PURE__*/ function() {
239
301
  }
240
302
  };
241
303
  _proto.getProcess = function getProcess(id) {
242
- return this.processes.find(function(p) {
304
+ return (0, _compatts.arrayFind)(this.processes, function(p) {
243
305
  return p.id === id;
244
306
  });
245
307
  };
@@ -266,42 +328,16 @@ var ProcessStore = /*#__PURE__*/ function() {
266
328
  }
267
329
  return process.lines.length;
268
330
  };
269
- // UI state mutations
331
+ // === VIEW STATE: Mutations ===
270
332
  _proto.setMode = function setMode(mode) {
271
333
  this.mode = mode;
272
334
  if (mode === 'interactive') {
273
- this.selectedIndex = 0;
335
+ this.listNav.setPosition(0);
274
336
  }
275
337
  this.notify();
276
338
  };
277
- // Interactive mode navigation
278
- _proto.selectNext = function selectNext(visibleCount) {
279
- if (this.processes.length > 0) {
280
- this.selectedIndex = (this.selectedIndex + 1) % this.processes.length;
281
- this.adjustListScroll(visibleCount);
282
- this.notify();
283
- }
284
- };
285
- _proto.selectPrev = function selectPrev(visibleCount) {
286
- if (this.processes.length > 0) {
287
- this.selectedIndex = (this.selectedIndex - 1 + this.processes.length) % this.processes.length;
288
- this.adjustListScroll(visibleCount);
289
- this.notify();
290
- }
291
- };
292
- _proto.adjustListScroll = function adjustListScroll(visibleCount) {
293
- if (!visibleCount || visibleCount <= 0) return;
294
- // Ensure selected item is visible in viewport
295
- if (this.selectedIndex < this.listScrollOffset) {
296
- // Selected is above viewport - scroll up
297
- this.listScrollOffset = this.selectedIndex;
298
- } else if (this.selectedIndex >= this.listScrollOffset + visibleCount) {
299
- // Selected is below viewport - scroll down
300
- this.listScrollOffset = this.selectedIndex - visibleCount + 1;
301
- }
302
- };
303
339
  _proto.getSelectedProcess = function getSelectedProcess() {
304
- return this.processes[this.selectedIndex];
340
+ return this.processes[this.listNav.position];
305
341
  };
306
342
  // Error footer methods (for non-interactive mode)
307
343
  _proto.toggleErrorFooter = function toggleErrorFooter() {
@@ -314,85 +350,138 @@ var ProcessStore = /*#__PURE__*/ function() {
314
350
  this.notify();
315
351
  }
316
352
  };
317
- _proto.getErrorLines = function getErrorLines() {
318
- var _this = this;
319
- return this.getFailedProcesses().map(function(p) {
320
- return {
321
- processName: p.group || p.title,
322
- lines: _this.getProcessLines(p.id)
323
- };
324
- });
353
+ // === NAVIGATION: List (delegates to listNav) ===
354
+ _proto.selectNext = function selectNext(visibleCount) {
355
+ this.listNav.down();
356
+ if (visibleCount) {
357
+ this.listNav.ensureVisible(visibleCount);
358
+ }
325
359
  };
326
- // Expansion methods
327
- _proto.toggleExpand = function toggleExpand() {
328
- var selected = this.getSelectedProcess();
329
- if (!selected) return;
330
- if (this.expandedId === selected.id) {
331
- // Collapse
332
- this.expandedId = null;
333
- this.scrollOffset = 0;
334
- } else {
335
- // Expand
336
- this.expandedId = selected.id;
337
- this.scrollOffset = 0;
360
+ _proto.selectPrev = function selectPrev(visibleCount) {
361
+ this.listNav.up();
362
+ if (visibleCount) {
363
+ this.listNav.ensureVisible(visibleCount);
338
364
  }
339
- this.notify();
340
365
  };
341
- _proto.collapse = function collapse() {
342
- this.expandedId = null;
343
- this.scrollOffset = 0;
344
- this.notify();
366
+ _proto.selectPageDown = function selectPageDown(pageSize, visibleCount) {
367
+ this.listNav.pageDown(pageSize, visibleCount);
368
+ };
369
+ _proto.selectPageUp = function selectPageUp(pageSize, visibleCount) {
370
+ this.listNav.pageUp(pageSize, visibleCount);
371
+ };
372
+ _proto.selectFirst = function selectFirst(visibleCount) {
373
+ this.listNav.toStart();
374
+ if (visibleCount) {
375
+ this.listNav.ensureVisible(visibleCount);
376
+ }
377
+ };
378
+ _proto.selectLast = function selectLast(visibleCount) {
379
+ this.listNav.toEnd();
380
+ if (visibleCount) {
381
+ this.listNav.ensureVisible(visibleCount);
382
+ }
383
+ };
384
+ _proto.clampListViewport = function clampListViewport(visibleCount) {
385
+ var changed = this.listNav.clampViewport(visibleCount);
386
+ if (changed) {
387
+ this.notify();
388
+ }
389
+ };
390
+ // === NAVIGATION: Expanded content (delegates to process.scrollNav) ===
391
+ _proto.getExpandedNav = function getExpandedNav() {
392
+ var _this_getProcess;
393
+ if (!this.expandedId) return undefined;
394
+ var nav = (_this_getProcess = this.getProcess(this.expandedId)) === null || _this_getProcess === void 0 ? void 0 : _this_getProcess.scrollNav;
395
+ if (!nav) return undefined;
396
+ return {
397
+ nav: nav,
398
+ id: this.expandedId
399
+ };
345
400
  };
346
401
  _proto.scrollDown = function scrollDown(maxVisible) {
347
- if (!this.expandedId) return;
348
- var lineCount = this.getProcessLineCount(this.expandedId);
349
- if (lineCount === 0) return;
402
+ var expanded = this.getExpandedNav();
403
+ if (!expanded) return;
404
+ var lineCount = this.getProcessLineCount(expanded.id);
350
405
  var maxOffset = Math.max(0, lineCount - maxVisible);
351
- if (this.scrollOffset < maxOffset) {
352
- this.scrollOffset++;
353
- this.notify();
406
+ // Only scroll if not at bottom
407
+ if (expanded.nav.position < maxOffset) {
408
+ expanded.nav.down();
354
409
  }
355
410
  };
356
411
  _proto.scrollUp = function scrollUp() {
357
- if (!this.expandedId) return;
358
- if (this.scrollOffset > 0) {
359
- this.scrollOffset--;
360
- this.notify();
412
+ var expanded = this.getExpandedNav();
413
+ if (!expanded) return;
414
+ if (expanded.nav.position > 0) {
415
+ expanded.nav.up();
361
416
  }
362
417
  };
363
- // Page scrolling (scroll by maxVisible lines at once)
364
- _proto.scrollPageDown = function scrollPageDown(maxVisible) {
365
- if (!this.expandedId) return;
366
- var lineCount = this.getProcessLineCount(this.expandedId);
367
- if (lineCount === 0) return;
368
- var maxOffset = Math.max(0, lineCount - maxVisible);
369
- this.scrollOffset = Math.min(this.scrollOffset + maxVisible, maxOffset);
418
+ _proto.scrollPageDown = function scrollPageDown(pageSize) {
419
+ var expanded = this.getExpandedNav();
420
+ if (!expanded) return;
421
+ var lineCount = this.getProcessLineCount(expanded.id);
422
+ var maxOffset = Math.max(0, lineCount - pageSize);
423
+ // Clamp to max offset
424
+ var newPosition = Math.min(expanded.nav.position + pageSize, maxOffset);
425
+ expanded.nav.setPosition(newPosition);
370
426
  this.notify();
371
427
  };
372
- _proto.scrollPageUp = function scrollPageUp(maxVisible) {
373
- if (!this.expandedId) return;
374
- this.scrollOffset = Math.max(0, this.scrollOffset - maxVisible);
428
+ _proto.scrollPageUp = function scrollPageUp(pageSize) {
429
+ var expanded = this.getExpandedNav();
430
+ if (!expanded) return;
431
+ var newPosition = Math.max(0, expanded.nav.position - pageSize);
432
+ expanded.nav.setPosition(newPosition);
375
433
  this.notify();
376
434
  };
377
- // Jump to top/bottom
378
435
  _proto.scrollToTop = function scrollToTop() {
379
- if (!this.expandedId) return;
380
- this.scrollOffset = 0;
381
- this.notify();
436
+ var expanded = this.getExpandedNav();
437
+ if (!expanded) return;
438
+ expanded.nav.toStart();
382
439
  };
383
440
  _proto.scrollToBottom = function scrollToBottom(maxVisible) {
384
- if (!this.expandedId) return;
385
- var lineCount = this.getProcessLineCount(this.expandedId);
386
- if (lineCount === 0) return;
387
- this.scrollOffset = Math.max(0, lineCount - maxVisible);
441
+ var expanded = this.getExpandedNav();
442
+ if (!expanded) return;
443
+ var lineCount = this.getProcessLineCount(expanded.id);
444
+ var newPosition = Math.max(0, lineCount - maxVisible);
445
+ expanded.nav.setPosition(newPosition);
446
+ this.notify();
447
+ };
448
+ // === EXPANSION ===
449
+ _proto.toggleExpand = function toggleExpand(visibleCountWhenExpanded, visibleCountWhenCollapsed) {
450
+ var selected = this.getSelectedProcess();
451
+ if (!selected) return;
452
+ if (this.expandedId === selected.id) {
453
+ // Collapse (keep scroll position for later)
454
+ this.expandedId = null;
455
+ // Adjust viewport to avoid empty space at bottom
456
+ if (visibleCountWhenCollapsed) {
457
+ this.listNav.clampViewport(visibleCountWhenCollapsed);
458
+ }
459
+ } else {
460
+ // Expand (scroll position is preserved in process.scrollNav)
461
+ this.expandedId = selected.id;
462
+ // Adjust list scroll to keep expanded process visible
463
+ if (visibleCountWhenExpanded) {
464
+ this.listNav.ensureVisible(visibleCountWhenExpanded);
465
+ }
466
+ }
467
+ this.notify();
468
+ };
469
+ _proto.collapse = function collapse(visibleCountWhenCollapsed) {
470
+ // Collapse but keep scroll position in process
471
+ this.expandedId = null;
472
+ // Adjust viewport to avoid empty space at bottom
473
+ if (visibleCountWhenCollapsed) {
474
+ this.listNav.clampViewport(visibleCountWhenCollapsed);
475
+ }
388
476
  this.notify();
389
477
  };
390
- // Exit signaling
478
+ // === EXIT ===
391
479
  _proto.signalExit = function signalExit(callback) {
392
480
  this.shouldExit = true;
393
481
  this.exitCallback = callback;
394
482
  this.notify();
395
483
  };
484
+ // === RESET ===
396
485
  _proto.reset = function reset() {
397
486
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
398
487
  try {
@@ -421,14 +510,12 @@ var ProcessStore = /*#__PURE__*/ function() {
421
510
  this.shouldExit = false;
422
511
  this.exitCallback = null;
423
512
  this.mode = 'normal';
424
- this.selectedIndex = 0;
513
+ this.listNav.reset();
425
514
  this.expandedId = null;
426
- this.scrollOffset = 0;
427
- this.listScrollOffset = 0;
428
515
  this.errorFooterExpanded = false;
429
516
  this.header = undefined;
430
517
  };
431
- // Public notify for session to trigger updates when terminal buffer changes
518
+ // === INFRASTRUCTURE ===
432
519
  _proto.notify = function notify() {
433
520
  this.bufferVersion++;
434
521
  this.listeners.forEach(function(l) {
@@ -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, SessionOptions } from '../types.ts';\nimport { LineType } from '../types.ts';\n\ntype Listener = () => void;\ntype Mode = 'normal' | 'interactive';\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 expandedId: string | null = null;\n private scrollOffset = 0;\n private listScrollOffset = 0; // Viewport offset for process list\n private errorFooterExpanded = false; // For non-interactive error footer\n private bufferVersion = 0; // Increments on every notify() to trigger re-renders\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 + this.getProcessLineCount(p.id), 0);\n };\n\n // UI state getters\n getMode = (): Mode => this.mode;\n getSelectedIndex = (): number => this.selectedIndex;\n getExpandedId = (): string | null => this.expandedId;\n getScrollOffset = (): number => this.scrollOffset;\n getListScrollOffset = (): number => this.listScrollOffset;\n getErrorFooterExpanded = (): boolean => this.errorFooterExpanded;\n getBufferVersion = (): number => this.bufferVersion;\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 // Auto-expand error footer when all complete with errors (non-interactive only)\n if (!this.isInteractive && this.isAllComplete() && this.getErrorCount() > 0) {\n this.errorFooterExpanded = true;\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 // Get rendered lines from terminal buffer or fallback to lines array\n getProcessLines(id: string): Line[] {\n const process = this.getProcess(id);\n if (!process) return [];\n if (process.terminalBuffer) {\n return process.terminalBuffer.getLines().map((text) => ({\n type: LineType.stdout,\n text,\n }));\n }\n return process.lines;\n }\n\n // Get line count from terminal buffer or lines array\n getProcessLineCount(id: string): number {\n const process = this.getProcess(id);\n if (!process) return 0;\n if (process.terminalBuffer) {\n return process.terminalBuffer.lineCount;\n }\n return process.lines.length;\n }\n\n // UI state mutations\n setMode(mode: Mode): void {\n this.mode = mode;\n if (mode === 'interactive') {\n this.selectedIndex = 0;\n }\n this.notify();\n }\n\n // Interactive mode navigation\n selectNext(visibleCount?: number): void {\n if (this.processes.length > 0) {\n this.selectedIndex = (this.selectedIndex + 1) % this.processes.length;\n this.adjustListScroll(visibleCount);\n this.notify();\n }\n }\n\n selectPrev(visibleCount?: number): void {\n if (this.processes.length > 0) {\n this.selectedIndex = (this.selectedIndex - 1 + this.processes.length) % this.processes.length;\n this.adjustListScroll(visibleCount);\n this.notify();\n }\n }\n\n private adjustListScroll(visibleCount?: number): void {\n if (!visibleCount || visibleCount <= 0) return;\n\n // Ensure selected item is visible in viewport\n if (this.selectedIndex < this.listScrollOffset) {\n // Selected is above viewport - scroll up\n this.listScrollOffset = this.selectedIndex;\n } else if (this.selectedIndex >= this.listScrollOffset + visibleCount) {\n // Selected is below viewport - scroll down\n this.listScrollOffset = this.selectedIndex - visibleCount + 1;\n }\n }\n\n getSelectedProcess(): ChildProcess | undefined {\n return this.processes[this.selectedIndex];\n }\n\n // Error footer methods (for non-interactive mode)\n toggleErrorFooter(): void {\n this.errorFooterExpanded = !this.errorFooterExpanded;\n this.notify();\n }\n\n expandErrorFooter(): void {\n if (!this.errorFooterExpanded) {\n this.errorFooterExpanded = true;\n this.notify();\n }\n }\n\n getErrorLines(): Array<{ processName: string; lines: Line[] }> {\n return this.getFailedProcesses().map((p) => ({\n processName: p.group || p.title,\n lines: this.getProcessLines(p.id),\n }));\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 lineCount = this.getProcessLineCount(this.expandedId);\n if (lineCount === 0) return;\n\n const maxOffset = Math.max(0, lineCount - 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 // Page scrolling (scroll by maxVisible lines at once)\n scrollPageDown(maxVisible: number): void {\n if (!this.expandedId) return;\n const lineCount = this.getProcessLineCount(this.expandedId);\n if (lineCount === 0) return;\n\n const maxOffset = Math.max(0, lineCount - maxVisible);\n this.scrollOffset = Math.min(this.scrollOffset + maxVisible, maxOffset);\n this.notify();\n }\n\n scrollPageUp(maxVisible: number): void {\n if (!this.expandedId) return;\n this.scrollOffset = Math.max(0, this.scrollOffset - maxVisible);\n this.notify();\n }\n\n // Jump to top/bottom\n scrollToTop(): void {\n if (!this.expandedId) return;\n this.scrollOffset = 0;\n this.notify();\n }\n\n scrollToBottom(maxVisible: number): void {\n if (!this.expandedId) return;\n const lineCount = this.getProcessLineCount(this.expandedId);\n if (lineCount === 0) return;\n\n this.scrollOffset = Math.max(0, lineCount - maxVisible);\n this.notify();\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 // Dispose terminal buffers before clearing\n for (const process of this.processes) {\n process.terminalBuffer?.dispose();\n }\n this.processes = [];\n this.completedIds = [];\n this.shouldExit = false;\n this.exitCallback = null;\n this.mode = 'normal';\n this.selectedIndex = 0;\n this.expandedId = null;\n this.scrollOffset = 0;\n this.listScrollOffset = 0;\n this.errorFooterExpanded = false;\n this.header = undefined;\n }\n\n // Public notify for session to trigger updates when terminal buffer changes\n notify(): void {\n this.bufferVersion++;\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","expandedId","scrollOffset","listScrollOffset","errorFooterExpanded","bufferVersion","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","getProcessLineCount","getMode","getSelectedIndex","getExpandedId","getScrollOffset","getListScrollOffset","getErrorFooterExpanded","getBufferVersion","getHeader","header","getShowStatusBar","getIsInteractive","isAllComplete","every","getShouldExit","getExitCallback","interactive","addProcess","process","notify","updateProcess","update","oldProcess","wasRunning","isNowComplete","includes","appendLines","newLines","lines","concat","getProcess","getProcessLines","terminalBuffer","getLines","text","type","LineType","stdout","lineCount","setMode","selectNext","visibleCount","adjustListScroll","selectPrev","getSelectedProcess","toggleErrorFooter","expandErrorFooter","getErrorLines","processName","toggleExpand","selected","collapse","scrollDown","maxVisible","maxOffset","scrollUp","scrollPageDown","min","scrollPageUp","scrollToTop","scrollToBottom","signalExit","callback","reset","dispose","forEach","l"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/state/processStore.ts"],"sourcesContent":["import { arrayFind } from '../compat.ts';\nimport { DEFAULT_COLUMN_WIDTH } from '../constants.ts';\nimport type { ChildProcess, Line, SessionOptions } from '../types.ts';\nimport { LineType } from '../types.ts';\nimport { createNavigator, type Navigator } from './Navigator.ts';\n\ntype Listener = () => void;\ntype Mode = 'normal' | 'interactive';\n\nexport class ProcessStore {\n // === DATA: Process collection ===\n private processes: ChildProcess[] = [];\n private completedIds: string[] = []; // Track completion order\n\n // === NAVIGATION: List cursor ===\n private listNav: Navigator;\n\n // === VIEW STATE ===\n private mode: Mode = 'normal';\n private expandedId: string | null = null;\n private errorFooterExpanded = false; // For non-interactive error footer\n\n // === SESSION CONFIG (immutable after construction) ===\n private header: string | undefined;\n private showStatusBar = false;\n private isInteractive = false;\n\n // === INFRASTRUCTURE ===\n private listeners = new Set<Listener>();\n private shouldExit = false;\n private exitCallback: (() => void) | null = null;\n private bufferVersion = 0; // Increments on every notify() to trigger re-renders\n\n constructor(options: SessionOptions = {}) {\n this.header = options.header;\n this.showStatusBar = options.showStatusBar ?? false;\n this.isInteractive = options.interactive ?? false;\n\n // Create list navigator with wrap-around behavior\n this.listNav = createNavigator({\n getLength: () => this.processes.length,\n wrap: true,\n onMove: () => this.notify(),\n });\n }\n\n // === SUBSCRIPTION API (useSyncExternalStore) ===\n\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 // === DATA: Queries ===\n\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) => arrayFind(this.processes, (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 + this.getProcessLineCount(p.id), 0);\n };\n\n getErrorLines(): Array<{ processName: string; lines: Line[] }> {\n return this.getFailedProcesses().map((p) => ({\n processName: p.group || p.title,\n lines: this.getProcessLines(p.id),\n }));\n }\n\n // === DATA: Mutations ===\n\n addProcess(process: ChildProcess): void {\n // Create scroll navigator for this process\n const processWithNav: ChildProcess = {\n ...process,\n scrollNav: createNavigator({\n getLength: () => this.getProcessLineCount(processWithNav.id),\n wrap: false,\n onMove: () => this.notify(),\n }),\n };\n this.processes = [...this.processes, processWithNav];\n this.notify();\n }\n\n updateProcess(id: string, update: Partial<ChildProcess>): void {\n const oldProcess = arrayFind(this.processes, (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 // Auto-expand error footer when all complete with errors (non-interactive only)\n if (!this.isInteractive && this.isAllComplete() && this.getErrorCount() > 0) {\n this.errorFooterExpanded = true;\n }\n\n this.notify();\n }\n\n appendLines(id: string, newLines: Line[]): void {\n const process = arrayFind(this.processes, (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 arrayFind(this.processes, (p) => p.id === id);\n }\n\n // Get rendered lines from terminal buffer or fallback to lines array\n getProcessLines(id: string): Line[] {\n const process = this.getProcess(id);\n if (!process) return [];\n if (process.terminalBuffer) {\n return process.terminalBuffer.getLines().map((text) => ({\n type: LineType.stdout,\n text,\n }));\n }\n return process.lines;\n }\n\n // Get line count from terminal buffer or lines array\n getProcessLineCount(id: string): number {\n const process = this.getProcess(id);\n if (!process) return 0;\n if (process.terminalBuffer) {\n return process.terminalBuffer.lineCount;\n }\n return process.lines.length;\n }\n\n // === VIEW STATE: Getters ===\n\n getMode = (): Mode => this.mode;\n getSelectedIndex = (): number => this.listNav.position;\n getExpandedId = (): string | null => this.expandedId;\n getListScrollOffset = (): number => this.listNav.viewportOffset;\n getErrorFooterExpanded = (): boolean => this.errorFooterExpanded;\n getBufferVersion = (): number => this.bufferVersion;\n\n // Get scroll offset for expanded process (or 0 if none)\n getScrollOffset = (): number => {\n if (!this.expandedId) return 0;\n const process = this.getProcess(this.expandedId);\n return process?.scrollNav?.position ?? 0;\n };\n\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 // === VIEW STATE: Mutations ===\n\n setMode(mode: Mode): void {\n this.mode = mode;\n if (mode === 'interactive') {\n this.listNav.setPosition(0);\n }\n this.notify();\n }\n\n getSelectedProcess(): ChildProcess | undefined {\n return this.processes[this.listNav.position];\n }\n\n // Error footer methods (for non-interactive mode)\n toggleErrorFooter(): void {\n this.errorFooterExpanded = !this.errorFooterExpanded;\n this.notify();\n }\n\n expandErrorFooter(): void {\n if (!this.errorFooterExpanded) {\n this.errorFooterExpanded = true;\n this.notify();\n }\n }\n\n // === NAVIGATION: List (delegates to listNav) ===\n\n selectNext(visibleCount?: number): void {\n this.listNav.down();\n if (visibleCount) {\n this.listNav.ensureVisible(visibleCount);\n }\n }\n\n selectPrev(visibleCount?: number): void {\n this.listNav.up();\n if (visibleCount) {\n this.listNav.ensureVisible(visibleCount);\n }\n }\n\n selectPageDown(pageSize: number, visibleCount?: number): void {\n this.listNav.pageDown(pageSize, visibleCount);\n }\n\n selectPageUp(pageSize: number, visibleCount?: number): void {\n this.listNav.pageUp(pageSize, visibleCount);\n }\n\n selectFirst(visibleCount?: number): void {\n this.listNav.toStart();\n if (visibleCount) {\n this.listNav.ensureVisible(visibleCount);\n }\n }\n\n selectLast(visibleCount?: number): void {\n this.listNav.toEnd();\n if (visibleCount) {\n this.listNav.ensureVisible(visibleCount);\n }\n }\n\n clampListViewport(visibleCount: number): void {\n const changed = this.listNav.clampViewport(visibleCount);\n if (changed) {\n this.notify();\n }\n }\n\n // === NAVIGATION: Expanded content (delegates to process.scrollNav) ===\n\n private getExpandedNav(): { nav: Navigator; id: string } | undefined {\n if (!this.expandedId) return undefined;\n const nav = this.getProcess(this.expandedId)?.scrollNav;\n if (!nav) return undefined;\n return { nav, id: this.expandedId };\n }\n\n scrollDown(maxVisible: number): void {\n const expanded = this.getExpandedNav();\n if (!expanded) return;\n\n const lineCount = this.getProcessLineCount(expanded.id);\n const maxOffset = Math.max(0, lineCount - maxVisible);\n\n // Only scroll if not at bottom\n if (expanded.nav.position < maxOffset) {\n expanded.nav.down();\n }\n }\n\n scrollUp(): void {\n const expanded = this.getExpandedNav();\n if (!expanded) return;\n\n if (expanded.nav.position > 0) {\n expanded.nav.up();\n }\n }\n\n scrollPageDown(pageSize: number): void {\n const expanded = this.getExpandedNav();\n if (!expanded) return;\n\n const lineCount = this.getProcessLineCount(expanded.id);\n const maxOffset = Math.max(0, lineCount - pageSize);\n\n // Clamp to max offset\n const newPosition = Math.min(expanded.nav.position + pageSize, maxOffset);\n expanded.nav.setPosition(newPosition);\n this.notify();\n }\n\n scrollPageUp(pageSize: number): void {\n const expanded = this.getExpandedNav();\n if (!expanded) return;\n\n const newPosition = Math.max(0, expanded.nav.position - pageSize);\n expanded.nav.setPosition(newPosition);\n this.notify();\n }\n\n scrollToTop(): void {\n const expanded = this.getExpandedNav();\n if (!expanded) return;\n expanded.nav.toStart();\n }\n\n scrollToBottom(maxVisible: number): void {\n const expanded = this.getExpandedNav();\n if (!expanded) return;\n\n const lineCount = this.getProcessLineCount(expanded.id);\n const newPosition = Math.max(0, lineCount - maxVisible);\n expanded.nav.setPosition(newPosition);\n this.notify();\n }\n\n // === EXPANSION ===\n\n toggleExpand(visibleCountWhenExpanded?: number, visibleCountWhenCollapsed?: number): void {\n const selected = this.getSelectedProcess();\n if (!selected) return;\n\n if (this.expandedId === selected.id) {\n // Collapse (keep scroll position for later)\n this.expandedId = null;\n // Adjust viewport to avoid empty space at bottom\n if (visibleCountWhenCollapsed) {\n this.listNav.clampViewport(visibleCountWhenCollapsed);\n }\n } else {\n // Expand (scroll position is preserved in process.scrollNav)\n this.expandedId = selected.id;\n // Adjust list scroll to keep expanded process visible\n if (visibleCountWhenExpanded) {\n this.listNav.ensureVisible(visibleCountWhenExpanded);\n }\n }\n this.notify();\n }\n\n collapse(visibleCountWhenCollapsed?: number): void {\n // Collapse but keep scroll position in process\n this.expandedId = null;\n // Adjust viewport to avoid empty space at bottom\n if (visibleCountWhenCollapsed) {\n this.listNav.clampViewport(visibleCountWhenCollapsed);\n }\n this.notify();\n }\n\n // === EXIT ===\n\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 ===\n\n reset(): void {\n // Dispose terminal buffers before clearing\n for (const process of this.processes) {\n process.terminalBuffer?.dispose();\n }\n this.processes = [];\n this.completedIds = [];\n this.shouldExit = false;\n this.exitCallback = null;\n this.mode = 'normal';\n this.listNav.reset();\n this.expandedId = null;\n this.errorFooterExpanded = false;\n this.header = undefined;\n }\n\n // === INFRASTRUCTURE ===\n\n notify(): void {\n this.bufferVersion++;\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","mode","expandedId","errorFooterExpanded","showStatusBar","isInteractive","listeners","Set","shouldExit","exitCallback","bufferVersion","subscribe","listener","add","delete","getSnapshot","getRunningProcesses","filter","p","state","getCompletedProcesses","map","id","arrayFind","undefined","getFailedProcesses","getRunningCount","length","getMaxGroupLength","Math","DEFAULT_COLUMN_WIDTH","max","group","title","getDoneCount","getErrorCount","getErrorLineCount","reduce","total","getProcessLineCount","getMode","getSelectedIndex","listNav","position","getExpandedId","getListScrollOffset","viewportOffset","getErrorFooterExpanded","getBufferVersion","getScrollOffset","process","getProcess","scrollNav","getHeader","header","getShowStatusBar","getIsInteractive","isAllComplete","every","getShouldExit","getExitCallback","interactive","createNavigator","getLength","wrap","onMove","notify","getErrorLines","processName","lines","getProcessLines","addProcess","processWithNav","updateProcess","update","oldProcess","wasRunning","isNowComplete","includes","appendLines","newLines","concat","terminalBuffer","getLines","text","type","LineType","stdout","lineCount","setMode","setPosition","getSelectedProcess","toggleErrorFooter","expandErrorFooter","selectNext","visibleCount","down","ensureVisible","selectPrev","up","selectPageDown","pageSize","pageDown","selectPageUp","pageUp","selectFirst","toStart","selectLast","toEnd","clampListViewport","changed","clampViewport","getExpandedNav","nav","scrollDown","maxVisible","expanded","maxOffset","scrollUp","scrollPageDown","newPosition","min","scrollPageUp","scrollToTop","scrollToBottom","toggleExpand","visibleCountWhenExpanded","visibleCountWhenCollapsed","selected","collapse","signalExit","callback","reset","dispose","forEach","l"],"mappings":";;;;+BASaA;;;eAAAA;;;wBATa;2BACW;uBAEZ;2BACuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKzC,IAAA,AAAMA,6BAAN;;aAAMA;;YAwBCC,UAAAA,iEAA0B,CAAC;gCAxB5BD;QACX,mCAAmC;aAC3BE,YAA4B,EAAE;aAC9BC,eAAyB,EAAE,EAAE,yBAAyB;QAK9D,qBAAqB;aACbC,OAAa;aACbC,aAA4B;aAC5BC,sBAAsB,OAAO,mCAAmC;aAIhEC,gBAAgB;aAChBC,gBAAgB;QAExB,yBAAyB;aACjBC,YAAY,IAAIC;aAChBC,aAAa;aACbC,eAAoC;aACpCC,gBAAgB,GAAG,qDAAqD;QAehF,kDAAkD;aAElDC,YAAY,SAACC;YACX,MAAKN,SAAS,CAACO,GAAG,CAACD;YACnB,OAAO;uBAAM,MAAKN,SAAS,CAACQ,MAAM,CAACF;;QACrC;aAEAG,cAAc;mBAAsB,MAAKhB,SAAS;;QAElD,wBAAwB;aAExBiB,sBAAsB;YACpB,OAAO,MAAKjB,SAAS,CAACkB,MAAM,CAAC,SAACC;uBAAMA,EAAEC,KAAK,KAAK;;QAClD;aAEAC,wBAAwB;YACtB,6BAA6B;YAC7B,OAAO,MAAKpB,YAAY,CAACqB,GAAG,CAAC,SAACC;uBAAOC,IAAAA,mBAAS,EAAC,MAAKxB,SAAS,EAAE,SAACmB;2BAAMA,EAAEI,EAAE,KAAKA;;eAAKL,MAAM,CAAC,SAACC;uBAAyBA,MAAMM;;QAC7H;aAEAC,qBAAqB;YACnB,OAAO,MAAK1B,SAAS,CAACkB,MAAM,CAAC,SAACC;uBAAMA,EAAEC,KAAK,KAAK;;QAClD;QAEA,SAAS;aACTO,kBAAkB;mBAAc,MAAK3B,SAAS,CAACkB,MAAM,CAAC,SAACC;uBAAMA,EAAEC,KAAK,KAAK;eAAWQ,MAAM;;aAC1FC,oBAAoB;gBAEXC;YADP,IAAI,MAAK9B,SAAS,CAAC4B,MAAM,KAAK,GAAG,OAAOG,iCAAoB;YAC5D,OAAOD,CAAAA,QAAAA,MAAKE,GAAG,OAARF,OAAS,qBAAG,MAAK9B,SAAS,CAACsB,GAAG,CAAC,SAACH;uBAAM,AAACA,CAAAA,EAAEc,KAAK,IAAId,EAAEe,KAAK,AAAD,EAAGN,MAAM;;QAC1E;aACAO,eAAe;mBAAc,MAAKnC,SAAS,CAACkB,MAAM,CAAC,SAACC;uBAAMA,EAAEC,KAAK,KAAK;eAAWQ,MAAM;;aACvFQ,gBAAgB;mBAAc,MAAKpC,SAAS,CAACkB,MAAM,CAAC,SAACC;uBAAMA,EAAEC,KAAK,KAAK;eAASQ,MAAM;;aACtFS,oBAAoB;YAClB,OAAO,MAAKrC,SAAS,CAACkB,MAAM,CAAC,SAACC;uBAAMA,EAAEC,KAAK,KAAK;eAASkB,MAAM,CAAC,SAACC,OAAOpB;uBAAMoB,QAAQ,MAAKC,mBAAmB,CAACrB,EAAEI,EAAE;eAAG;QACxH;QA+EA,8BAA8B;aAE9BkB,UAAU;mBAAY,MAAKvC,IAAI;;aAC/BwC,mBAAmB;mBAAc,MAAKC,OAAO,CAACC,QAAQ;;aACtDC,gBAAgB;mBAAqB,MAAK1C,UAAU;;aACpD2C,sBAAsB;mBAAc,MAAKH,OAAO,CAACI,cAAc;;aAC/DC,yBAAyB;mBAAe,MAAK5C,mBAAmB;;aAChE6C,mBAAmB;mBAAc,MAAKtC,aAAa;;QAEnD,wDAAwD;aACxDuC,kBAAkB;gBAGTC;YAFP,IAAI,CAAC,MAAKhD,UAAU,EAAE,OAAO;YAC7B,IAAMgD,UAAU,MAAKC,UAAU,CAAC,MAAKjD,UAAU;gBACxCgD;YAAP,OAAOA,CAAAA,8BAAAA,oBAAAA,+BAAAA,qBAAAA,QAASE,SAAS,cAAlBF,yCAAAA,mBAAoBP,QAAQ,cAA5BO,yCAAAA,8BAAgC;QACzC;QAEA,6DAA6D;aAC7DG,YAAY;mBAA0B,MAAKC,MAAM;;aACjDC,mBAAmB;mBAAe,MAAKnD,aAAa;;aACpDoD,mBAAmB;mBAAe,MAAKnD,aAAa;;aACpDoD,gBAAgB;mBAAe,MAAK1D,SAAS,CAAC4B,MAAM,GAAG,KAAK,MAAK5B,SAAS,CAAC2D,KAAK,CAAC,SAACxC;uBAAMA,EAAEC,KAAK,KAAK;;;aAyLpGwC,gBAAgB;mBAAe,MAAKnD,UAAU;;aAC9CoD,kBAAkB;mBAA2B,MAAKnD,YAAY;;QA3U5D,IAAI,CAAC6C,MAAM,GAAGxD,QAAQwD,MAAM;YACPxD;QAArB,IAAI,CAACM,aAAa,GAAGN,CAAAA,yBAAAA,QAAQM,aAAa,cAArBN,oCAAAA,yBAAyB;YACzBA;QAArB,IAAI,CAACO,aAAa,GAAGP,CAAAA,uBAAAA,QAAQ+D,WAAW,cAAnB/D,kCAAAA,uBAAuB;QAE5C,kDAAkD;QAClD,IAAI,CAAC4C,OAAO,GAAGoB,IAAAA,4BAAe,EAAC;YAC7BC,WAAW;uBAAM,MAAKhE,SAAS,CAAC4B,MAAM;;YACtCqC,MAAM;YACNC,QAAQ;uBAAM,MAAKC,MAAM;;QAC3B;;iBAlCSrE;IAyEXsE,OAAAA,aAKC,GALDA,SAAAA;;QACE,OAAO,IAAI,CAAC1C,kBAAkB,GAAGJ,GAAG,CAAC,SAACH;mBAAO;gBAC3CkD,aAAalD,EAAEc,KAAK,IAAId,EAAEe,KAAK;gBAC/BoC,OAAO,MAAKC,eAAe,CAACpD,EAAEI,EAAE;YAClC;;IACF;IAEA,0BAA0B;IAE1BiD,OAAAA,UAYC,GAZDA,SAAAA,WAAWrB,OAAqB;;QAC9B,2CAA2C;QAC3C,IAAMsB,iBAA+B,wCAChCtB;YACHE,WAAWU,IAAAA,4BAAe,EAAC;gBACzBC,WAAW;2BAAM,MAAKxB,mBAAmB,CAACiC,eAAelD,EAAE;;gBAC3D0C,MAAM;gBACNC,QAAQ;2BAAM,MAAKC,MAAM;;YAC3B;;QAEF,IAAI,CAACnE,SAAS,GAAG,AAAC,qBAAG,IAAI,CAACA,SAAS,SAAlB;YAAoByE;SAAe;QACpD,IAAI,CAACN,MAAM;IACb;IAEAO,OAAAA,aAkBC,GAlBDA,SAAAA,cAAcnD,EAAU,EAAEoD,MAA6B;QACrD,IAAMC,aAAapD,IAAAA,mBAAS,EAAC,IAAI,CAACxB,SAAS,EAAE,SAACmB;mBAAMA,EAAEI,EAAE,KAAKA;;QAC7D,IAAMsD,aAAaD,CAAAA,uBAAAA,iCAAAA,WAAYxD,KAAK,MAAK;QACzC,IAAM0D,gBAAgBH,OAAOvD,KAAK,IAAIuD,OAAOvD,KAAK,KAAK;QAEvD,IAAI,CAACpB,SAAS,GAAG,IAAI,CAACA,SAAS,CAACsB,GAAG,CAAC,SAACH;mBAAOA,EAAEI,EAAE,KAAKA,KAAK,mBAAKJ,GAAMwD,UAAWxD;;QAEhF,yBAAyB;QACzB,IAAI0D,cAAcC,iBAAiB,CAAC,IAAI,CAAC7E,YAAY,CAAC8E,QAAQ,CAACxD,KAAK;YAClE,IAAI,CAACtB,YAAY,GAAG,AAAC,qBAAG,IAAI,CAACA,YAAY,SAArB;gBAAuBsB;aAAG;QAChD;QAEA,gFAAgF;QAChF,IAAI,CAAC,IAAI,CAACjB,aAAa,IAAI,IAAI,CAACoD,aAAa,MAAM,IAAI,CAACtB,aAAa,KAAK,GAAG;YAC3E,IAAI,CAAChC,mBAAmB,GAAG;QAC7B;QAEA,IAAI,CAAC+D,MAAM;IACb;IAEAa,OAAAA,WAKC,GALDA,SAAAA,YAAYzD,EAAU,EAAE0D,QAAgB;QACtC,IAAM9B,UAAU3B,IAAAA,mBAAS,EAAC,IAAI,CAACxB,SAAS,EAAE,SAACmB;mBAAMA,EAAEI,EAAE,KAAKA;;QAC1D,IAAI4B,SAAS;YACX,IAAI,CAACuB,aAAa,CAACnD,IAAI;gBAAE+C,OAAOnB,QAAQmB,KAAK,CAACY,MAAM,CAACD;YAAU;QACjE;IACF;IAEA7B,OAAAA,UAEC,GAFDA,SAAAA,WAAW7B,EAAU;QACnB,OAAOC,IAAAA,mBAAS,EAAC,IAAI,CAACxB,SAAS,EAAE,SAACmB;mBAAMA,EAAEI,EAAE,KAAKA;;IACnD;IAEA,qEAAqE;IACrEgD,OAAAA,eAUC,GAVDA,SAAAA,gBAAgBhD,EAAU;QACxB,IAAM4B,UAAU,IAAI,CAACC,UAAU,CAAC7B;QAChC,IAAI,CAAC4B,SAAS,OAAO,EAAE;QACvB,IAAIA,QAAQgC,cAAc,EAAE;YAC1B,OAAOhC,QAAQgC,cAAc,CAACC,QAAQ,GAAG9D,GAAG,CAAC,SAAC+D;uBAAU;oBACtDC,MAAMC,iBAAQ,CAACC,MAAM;oBACrBH,MAAAA;gBACF;;QACF;QACA,OAAOlC,QAAQmB,KAAK;IACtB;IAEA,qDAAqD;IACrD9B,OAAAA,mBAOC,GAPDA,SAAAA,oBAAoBjB,EAAU;QAC5B,IAAM4B,UAAU,IAAI,CAACC,UAAU,CAAC7B;QAChC,IAAI,CAAC4B,SAAS,OAAO;QACrB,IAAIA,QAAQgC,cAAc,EAAE;YAC1B,OAAOhC,QAAQgC,cAAc,CAACM,SAAS;QACzC;QACA,OAAOtC,QAAQmB,KAAK,CAAC1C,MAAM;IAC7B;IAwBA,gCAAgC;IAEhC8D,OAAAA,OAMC,GANDA,SAAAA,QAAQxF,IAAU;QAChB,IAAI,CAACA,IAAI,GAAGA;QACZ,IAAIA,SAAS,eAAe;YAC1B,IAAI,CAACyC,OAAO,CAACgD,WAAW,CAAC;QAC3B;QACA,IAAI,CAACxB,MAAM;IACb;IAEAyB,OAAAA,kBAEC,GAFDA,SAAAA;QACE,OAAO,IAAI,CAAC5F,SAAS,CAAC,IAAI,CAAC2C,OAAO,CAACC,QAAQ,CAAC;IAC9C;IAEA,kDAAkD;IAClDiD,OAAAA,iBAGC,GAHDA,SAAAA;QACE,IAAI,CAACzF,mBAAmB,GAAG,CAAC,IAAI,CAACA,mBAAmB;QACpD,IAAI,CAAC+D,MAAM;IACb;IAEA2B,OAAAA,iBAKC,GALDA,SAAAA;QACE,IAAI,CAAC,IAAI,CAAC1F,mBAAmB,EAAE;YAC7B,IAAI,CAACA,mBAAmB,GAAG;YAC3B,IAAI,CAAC+D,MAAM;QACb;IACF;IAEA,kDAAkD;IAElD4B,OAAAA,UAKC,GALDA,SAAAA,WAAWC,YAAqB;QAC9B,IAAI,CAACrD,OAAO,CAACsD,IAAI;QACjB,IAAID,cAAc;YAChB,IAAI,CAACrD,OAAO,CAACuD,aAAa,CAACF;QAC7B;IACF;IAEAG,OAAAA,UAKC,GALDA,SAAAA,WAAWH,YAAqB;QAC9B,IAAI,CAACrD,OAAO,CAACyD,EAAE;QACf,IAAIJ,cAAc;YAChB,IAAI,CAACrD,OAAO,CAACuD,aAAa,CAACF;QAC7B;IACF;IAEAK,OAAAA,cAEC,GAFDA,SAAAA,eAAeC,QAAgB,EAAEN,YAAqB;QACpD,IAAI,CAACrD,OAAO,CAAC4D,QAAQ,CAACD,UAAUN;IAClC;IAEAQ,OAAAA,YAEC,GAFDA,SAAAA,aAAaF,QAAgB,EAAEN,YAAqB;QAClD,IAAI,CAACrD,OAAO,CAAC8D,MAAM,CAACH,UAAUN;IAChC;IAEAU,OAAAA,WAKC,GALDA,SAAAA,YAAYV,YAAqB;QAC/B,IAAI,CAACrD,OAAO,CAACgE,OAAO;QACpB,IAAIX,cAAc;YAChB,IAAI,CAACrD,OAAO,CAACuD,aAAa,CAACF;QAC7B;IACF;IAEAY,OAAAA,UAKC,GALDA,SAAAA,WAAWZ,YAAqB;QAC9B,IAAI,CAACrD,OAAO,CAACkE,KAAK;QAClB,IAAIb,cAAc;YAChB,IAAI,CAACrD,OAAO,CAACuD,aAAa,CAACF;QAC7B;IACF;IAEAc,OAAAA,iBAKC,GALDA,SAAAA,kBAAkBd,YAAoB;QACpC,IAAMe,UAAU,IAAI,CAACpE,OAAO,CAACqE,aAAa,CAAChB;QAC3C,IAAIe,SAAS;YACX,IAAI,CAAC5C,MAAM;QACb;IACF;IAEA,wEAAwE;IAExE,OAAQ8C,cAKP,GALD,SAAQA;YAEM;QADZ,IAAI,CAAC,IAAI,CAAC9G,UAAU,EAAE,OAAOsB;QAC7B,IAAMyF,OAAM,mBAAA,IAAI,CAAC9D,UAAU,CAAC,IAAI,CAACjD,UAAU,eAA/B,uCAAA,iBAAkCkD,SAAS;QACvD,IAAI,CAAC6D,KAAK,OAAOzF;QACjB,OAAO;YAAEyF,KAAAA;YAAK3F,IAAI,IAAI,CAACpB,UAAU;QAAC;IACpC;IAEAgH,OAAAA,UAWC,GAXDA,SAAAA,WAAWC,UAAkB;QAC3B,IAAMC,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QAEf,IAAM5B,YAAY,IAAI,CAACjD,mBAAmB,CAAC6E,SAAS9F,EAAE;QACtD,IAAM+F,YAAYxF,KAAKE,GAAG,CAAC,GAAGyD,YAAY2B;QAE1C,+BAA+B;QAC/B,IAAIC,SAASH,GAAG,CAACtE,QAAQ,GAAG0E,WAAW;YACrCD,SAASH,GAAG,CAACjB,IAAI;QACnB;IACF;IAEAsB,OAAAA,QAOC,GAPDA,SAAAA;QACE,IAAMF,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QAEf,IAAIA,SAASH,GAAG,CAACtE,QAAQ,GAAG,GAAG;YAC7ByE,SAASH,GAAG,CAACd,EAAE;QACjB;IACF;IAEAoB,OAAAA,cAWC,GAXDA,SAAAA,eAAelB,QAAgB;QAC7B,IAAMe,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QAEf,IAAM5B,YAAY,IAAI,CAACjD,mBAAmB,CAAC6E,SAAS9F,EAAE;QACtD,IAAM+F,YAAYxF,KAAKE,GAAG,CAAC,GAAGyD,YAAYa;QAE1C,sBAAsB;QACtB,IAAMmB,cAAc3F,KAAK4F,GAAG,CAACL,SAASH,GAAG,CAACtE,QAAQ,GAAG0D,UAAUgB;QAC/DD,SAASH,GAAG,CAACvB,WAAW,CAAC8B;QACzB,IAAI,CAACtD,MAAM;IACb;IAEAwD,OAAAA,YAOC,GAPDA,SAAAA,aAAarB,QAAgB;QAC3B,IAAMe,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QAEf,IAAMI,cAAc3F,KAAKE,GAAG,CAAC,GAAGqF,SAASH,GAAG,CAACtE,QAAQ,GAAG0D;QACxDe,SAASH,GAAG,CAACvB,WAAW,CAAC8B;QACzB,IAAI,CAACtD,MAAM;IACb;IAEAyD,OAAAA,WAIC,GAJDA,SAAAA;QACE,IAAMP,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QACfA,SAASH,GAAG,CAACP,OAAO;IACtB;IAEAkB,OAAAA,cAQC,GARDA,SAAAA,eAAeT,UAAkB;QAC/B,IAAMC,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QAEf,IAAM5B,YAAY,IAAI,CAACjD,mBAAmB,CAAC6E,SAAS9F,EAAE;QACtD,IAAMkG,cAAc3F,KAAKE,GAAG,CAAC,GAAGyD,YAAY2B;QAC5CC,SAASH,GAAG,CAACvB,WAAW,CAAC8B;QACzB,IAAI,CAACtD,MAAM;IACb;IAEA,oBAAoB;IAEpB2D,OAAAA,YAoBC,GApBDA,SAAAA,aAAaC,wBAAiC,EAAEC,yBAAkC;QAChF,IAAMC,WAAW,IAAI,CAACrC,kBAAkB;QACxC,IAAI,CAACqC,UAAU;QAEf,IAAI,IAAI,CAAC9H,UAAU,KAAK8H,SAAS1G,EAAE,EAAE;YACnC,4CAA4C;YAC5C,IAAI,CAACpB,UAAU,GAAG;YAClB,iDAAiD;YACjD,IAAI6H,2BAA2B;gBAC7B,IAAI,CAACrF,OAAO,CAACqE,aAAa,CAACgB;YAC7B;QACF,OAAO;YACL,6DAA6D;YAC7D,IAAI,CAAC7H,UAAU,GAAG8H,SAAS1G,EAAE;YAC7B,sDAAsD;YACtD,IAAIwG,0BAA0B;gBAC5B,IAAI,CAACpF,OAAO,CAACuD,aAAa,CAAC6B;YAC7B;QACF;QACA,IAAI,CAAC5D,MAAM;IACb;IAEA+D,OAAAA,QAQC,GARDA,SAAAA,SAASF,yBAAkC;QACzC,+CAA+C;QAC/C,IAAI,CAAC7H,UAAU,GAAG;QAClB,iDAAiD;QACjD,IAAI6H,2BAA2B;YAC7B,IAAI,CAACrF,OAAO,CAACqE,aAAa,CAACgB;QAC7B;QACA,IAAI,CAAC7D,MAAM;IACb;IAEA,eAAe;IAEfgE,OAAAA,UAIC,GAJDA,SAAAA,WAAWC,QAAoB;QAC7B,IAAI,CAAC3H,UAAU,GAAG;QAClB,IAAI,CAACC,YAAY,GAAG0H;QACpB,IAAI,CAACjE,MAAM;IACb;IAKA,gBAAgB;IAEhBkE,OAAAA,KAcC,GAdDA,SAAAA;YAEO,kCAAA,2BAAA;;YADL,2CAA2C;YAC3C,QAAK,YAAiB,IAAI,CAACrI,SAAS,qBAA/B,SAAA,6BAAA,QAAA,yBAAA,iCAAiC;gBAAjC,IAAMmD,UAAN;oBACHA;iBAAAA,0BAAAA,QAAQgC,cAAc,cAAtBhC,8CAAAA,wBAAwBmF,OAAO;YACjC;;YAFK;YAAA;;;qBAAA,6BAAA;oBAAA;;;oBAAA;0BAAA;;;;QAGL,IAAI,CAACtI,SAAS,GAAG,EAAE;QACnB,IAAI,CAACC,YAAY,GAAG,EAAE;QACtB,IAAI,CAACQ,UAAU,GAAG;QAClB,IAAI,CAACC,YAAY,GAAG;QACpB,IAAI,CAACR,IAAI,GAAG;QACZ,IAAI,CAACyC,OAAO,CAAC0F,KAAK;QAClB,IAAI,CAAClI,UAAU,GAAG;QAClB,IAAI,CAACC,mBAAmB,GAAG;QAC3B,IAAI,CAACmD,MAAM,GAAG9B;IAChB;IAEA,yBAAyB;IAEzB0C,OAAAA,MAKC,GALDA,SAAAA;QACE,IAAI,CAACxD,aAAa;QAClB,IAAI,CAACJ,SAAS,CAACgI,OAAO,CAAC,SAACC;YACtBA;QACF;IACF;WA/XW1I;EAkYb,qEAAqE"}
@@ -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\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) => void;\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// Import type for TerminalBuffer (avoid circular dependency)\nimport type { TerminalBuffer } from './lib/TerminalBuffer.ts';\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 terminalBuffer?: TerminalBuffer; // Virtual terminal for ANSI interpretation\n expanded?: boolean;\n};\n"],"names":["LineType","stdout","stderr"],"mappings":";;;;+BAmBaA;;;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) => void;\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// Import type for TerminalBuffer (avoid circular dependency)\nimport type { TerminalBuffer } from './lib/TerminalBuffer.ts';\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 /** @internal Virtual terminal for ANSI interpretation */\n terminalBuffer?: TerminalBuffer;\n expanded?: boolean;\n /** @internal Per-process scroll navigation state */\n scrollNav?: import('./state/Navigator.ts').Navigator;\n};\n"],"names":["LineType","stdout","stderr"],"mappings":";;;;+BAmBaA;;;eAAAA;;;AAAN,IAAMA,WAAW;IACtBC,QAAQ;IACRC,QAAQ;AACV"}
@@ -13,3 +13,17 @@ export function stringEndsWith(str, search, position) {
13
13
  var len = position === undefined ? str.length : position;
14
14
  return str.lastIndexOf(search) === len - search.length;
15
15
  }
16
+ /**
17
+ * Array.prototype.find wrapper for Node.js 0.8+
18
+ * - Uses native find on Node 4.0+ / ES2015+
19
+ * - Falls back to loop on Node 0.8-3.x
20
+ */ var hasArrayFind = typeof Array.prototype.find === 'function';
21
+ export function arrayFind(arr, predicate) {
22
+ if (hasArrayFind) {
23
+ return arr.find(predicate);
24
+ }
25
+ for(var i = 0; i < arr.length; i++){
26
+ if (predicate(arr[i], i, arr)) return arr[i];
27
+ }
28
+ return undefined;
29
+ }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/compat.ts"],"sourcesContent":["/**\n * Compatibility Layer for Node.js 0.8+\n * Local to this package - contains only needed functions.\n */\n\n/**\n * String.prototype.endsWith wrapper for Node.js 0.8+\n * - Uses native endsWith on Node 4.0+ / ES2015+\n * - Falls back to lastIndexOf on Node 0.8-3.x\n */\nvar hasEndsWith = typeof String.prototype.endsWith === 'function';\n\nexport function stringEndsWith(str: string, search: string, position?: number): boolean {\n if (hasEndsWith) {\n return str.endsWith(search, position);\n }\n var len = position === undefined ? str.length : position;\n return str.lastIndexOf(search) === len - search.length;\n}\n"],"names":["hasEndsWith","String","prototype","endsWith","stringEndsWith","str","search","position","len","undefined","length","lastIndexOf"],"mappings":"AAAA;;;CAGC,GAED;;;;CAIC,GACD,IAAIA,cAAc,OAAOC,OAAOC,SAAS,CAACC,QAAQ,KAAK;AAEvD,OAAO,SAASC,eAAeC,GAAW,EAAEC,MAAc,EAAEC,QAAiB;IAC3E,IAAIP,aAAa;QACf,OAAOK,IAAIF,QAAQ,CAACG,QAAQC;IAC9B;IACA,IAAIC,MAAMD,aAAaE,YAAYJ,IAAIK,MAAM,GAAGH;IAChD,OAAOF,IAAIM,WAAW,CAACL,YAAYE,MAAMF,OAAOI,MAAM;AACxD"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/compat.ts"],"sourcesContent":["/**\n * Compatibility Layer for Node.js 0.8+\n * Local to this package - contains only needed functions.\n */\n\n/**\n * String.prototype.endsWith wrapper for Node.js 0.8+\n * - Uses native endsWith on Node 4.0+ / ES2015+\n * - Falls back to lastIndexOf on Node 0.8-3.x\n */\nvar hasEndsWith = typeof String.prototype.endsWith === 'function';\n\nexport function stringEndsWith(str: string, search: string, position?: number): boolean {\n if (hasEndsWith) {\n return str.endsWith(search, position);\n }\n var len = position === undefined ? str.length : position;\n return str.lastIndexOf(search) === len - search.length;\n}\n\n/**\n * Array.prototype.find wrapper for Node.js 0.8+\n * - Uses native find on Node 4.0+ / ES2015+\n * - Falls back to loop on Node 0.8-3.x\n */\nvar hasArrayFind = typeof Array.prototype.find === 'function';\n\nexport function arrayFind<T>(arr: T[], predicate: (item: T, index: number, arr: T[]) => boolean): T | undefined {\n if (hasArrayFind) {\n return arr.find(predicate);\n }\n for (var i = 0; i < arr.length; i++) {\n if (predicate(arr[i], i, arr)) return arr[i];\n }\n return undefined;\n}\n"],"names":["hasEndsWith","String","prototype","endsWith","stringEndsWith","str","search","position","len","undefined","length","lastIndexOf","hasArrayFind","Array","find","arrayFind","arr","predicate","i"],"mappings":"AAAA;;;CAGC,GAED;;;;CAIC,GACD,IAAIA,cAAc,OAAOC,OAAOC,SAAS,CAACC,QAAQ,KAAK;AAEvD,OAAO,SAASC,eAAeC,GAAW,EAAEC,MAAc,EAAEC,QAAiB;IAC3E,IAAIP,aAAa;QACf,OAAOK,IAAIF,QAAQ,CAACG,QAAQC;IAC9B;IACA,IAAIC,MAAMD,aAAaE,YAAYJ,IAAIK,MAAM,GAAGH;IAChD,OAAOF,IAAIM,WAAW,CAACL,YAAYE,MAAMF,OAAOI,MAAM;AACxD;AAEA;;;;CAIC,GACD,IAAIE,eAAe,OAAOC,MAAMX,SAAS,CAACY,IAAI,KAAK;AAEnD,OAAO,SAASC,UAAaC,GAAQ,EAAEC,SAAwD;IAC7F,IAAIL,cAAc;QAChB,OAAOI,IAAIF,IAAI,CAACG;IAClB;IACA,IAAK,IAAIC,IAAI,GAAGA,IAAIF,IAAIN,MAAM,EAAEQ,IAAK;QACnC,IAAID,UAAUD,GAAG,CAACE,EAAE,EAAEA,GAAGF,MAAM,OAAOA,GAAG,CAACE,EAAE;IAC9C;IACA,OAAOT;AACT"}