spawn-term 3.0.4 → 3.0.6
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.
- package/dist/cjs/components/App.js +28 -56
- package/dist/cjs/components/App.js.map +1 -1
- package/dist/cjs/components/ErrorFooter.js +120 -0
- package/dist/cjs/components/ErrorFooter.js.map +1 -0
- package/dist/cjs/components/ExpandedOutput.js +0 -2
- package/dist/cjs/components/ExpandedOutput.js.map +1 -1
- package/dist/cjs/components/StatusBar.js +22 -33
- package/dist/cjs/components/StatusBar.js.map +1 -1
- package/dist/cjs/index-esm.js +4 -0
- package/dist/cjs/index-esm.js.map +1 -1
- package/dist/cjs/lib/TerminalBuffer.js +139 -0
- package/dist/cjs/lib/TerminalBuffer.js.map +1 -0
- package/dist/cjs/session.js +129 -56
- package/dist/cjs/session.js.map +1 -1
- package/dist/cjs/src/components/ErrorFooter.d.ts +11 -0
- package/dist/cjs/src/index-esm.d.ts +1 -0
- package/dist/cjs/src/lib/TerminalBuffer.d.ts +32 -0
- package/dist/cjs/src/state/processStore.d.ts +14 -7
- package/dist/cjs/src/types.d.ts +2 -0
- package/dist/cjs/state/processStore.js +79 -26
- package/dist/cjs/state/processStore.js.map +1 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/components/App.js +28 -56
- package/dist/esm/components/App.js.map +1 -1
- package/dist/esm/components/ErrorFooter.js +95 -0
- package/dist/esm/components/ErrorFooter.js.map +1 -0
- package/dist/esm/components/ExpandedOutput.js +0 -2
- package/dist/esm/components/ExpandedOutput.js.map +1 -1
- package/dist/esm/components/StatusBar.js +22 -33
- package/dist/esm/components/StatusBar.js.map +1 -1
- package/dist/esm/index-esm.js +1 -0
- package/dist/esm/index-esm.js.map +1 -1
- package/dist/esm/lib/TerminalBuffer.js +62 -0
- package/dist/esm/lib/TerminalBuffer.js.map +1 -0
- package/dist/esm/session.js +112 -35
- package/dist/esm/session.js.map +1 -1
- package/dist/esm/src/components/ErrorFooter.d.ts +11 -0
- package/dist/esm/src/index-esm.d.ts +1 -0
- package/dist/esm/src/lib/TerminalBuffer.d.ts +32 -0
- package/dist/esm/src/state/processStore.d.ts +14 -7
- package/dist/esm/src/types.d.ts +2 -0
- package/dist/esm/state/processStore.js +53 -22
- package/dist/esm/state/processStore.js.map +1 -1
- package/dist/esm/types.js.map +1 -1
- package/package.json +2 -1
- package/dist/cjs/components/ErrorDetailModal.js +0 -115
- package/dist/cjs/components/ErrorDetailModal.js.map +0 -1
- package/dist/cjs/components/ErrorListModal.js +0 -135
- package/dist/cjs/components/ErrorListModal.js.map +0 -1
- package/dist/cjs/src/components/ErrorDetailModal.d.ts +0 -8
- package/dist/cjs/src/components/ErrorListModal.d.ts +0 -8
- package/dist/esm/components/ErrorDetailModal.js +0 -99
- package/dist/esm/components/ErrorDetailModal.js.map +0 -1
- package/dist/esm/components/ErrorListModal.js +0 -116
- package/dist/esm/components/ErrorListModal.js.map +0 -1
- package/dist/esm/src/components/ErrorDetailModal.d.ts +0 -8
- package/dist/esm/src/components/ErrorListModal.d.ts +0 -8
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "TerminalBuffer", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return TerminalBuffer;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
var _headless = /*#__PURE__*/ _interop_require_wildcard(require("@xterm/headless"));
|
|
12
|
+
function _class_call_check(instance, Constructor) {
|
|
13
|
+
if (!(instance instanceof Constructor)) {
|
|
14
|
+
throw new TypeError("Cannot call a class as a function");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function _defineProperties(target, props) {
|
|
18
|
+
for(var i = 0; i < props.length; i++){
|
|
19
|
+
var descriptor = props[i];
|
|
20
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
|
21
|
+
descriptor.configurable = true;
|
|
22
|
+
if ("value" in descriptor) descriptor.writable = true;
|
|
23
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function _create_class(Constructor, protoProps, staticProps) {
|
|
27
|
+
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
28
|
+
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
29
|
+
return Constructor;
|
|
30
|
+
}
|
|
31
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
32
|
+
if (typeof WeakMap !== "function") return null;
|
|
33
|
+
var cacheBabelInterop = new WeakMap();
|
|
34
|
+
var cacheNodeInterop = new WeakMap();
|
|
35
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
36
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
37
|
+
})(nodeInterop);
|
|
38
|
+
}
|
|
39
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
40
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
41
|
+
return obj;
|
|
42
|
+
}
|
|
43
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
44
|
+
return {
|
|
45
|
+
default: obj
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
49
|
+
if (cache && cache.has(obj)) {
|
|
50
|
+
return cache.get(obj);
|
|
51
|
+
}
|
|
52
|
+
var newObj = {
|
|
53
|
+
__proto__: null
|
|
54
|
+
};
|
|
55
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
56
|
+
for(var key in obj){
|
|
57
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
58
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
59
|
+
if (desc && (desc.get || desc.set)) {
|
|
60
|
+
Object.defineProperty(newObj, key, desc);
|
|
61
|
+
} else {
|
|
62
|
+
newObj[key] = obj[key];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
newObj.default = obj;
|
|
67
|
+
if (cache) {
|
|
68
|
+
cache.set(obj, newObj);
|
|
69
|
+
}
|
|
70
|
+
return newObj;
|
|
71
|
+
}
|
|
72
|
+
var _xterm_default;
|
|
73
|
+
// Handle both ESM and CJS module formats
|
|
74
|
+
var Terminal = _headless.Terminal || ((_xterm_default = _headless.default) === null || _xterm_default === void 0 ? void 0 : _xterm_default.Terminal);
|
|
75
|
+
var TerminalBuffer = /*#__PURE__*/ function() {
|
|
76
|
+
"use strict";
|
|
77
|
+
function TerminalBuffer(cols) {
|
|
78
|
+
var scrollback = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 10000;
|
|
79
|
+
_class_call_check(this, TerminalBuffer);
|
|
80
|
+
this.terminal = new Terminal({
|
|
81
|
+
cols: cols,
|
|
82
|
+
rows: 50,
|
|
83
|
+
scrollback: scrollback,
|
|
84
|
+
allowProposedApi: true
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
var _proto = TerminalBuffer.prototype;
|
|
88
|
+
/**
|
|
89
|
+
* Write raw data to the terminal buffer.
|
|
90
|
+
* The terminal interprets all ANSI sequences automatically.
|
|
91
|
+
*/ _proto.write = function write(data) {
|
|
92
|
+
var str = typeof data === 'string' ? data : data.toString('utf8');
|
|
93
|
+
this.terminal.write(str);
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Resize the terminal width.
|
|
97
|
+
*/ _proto.resize = function resize(cols) {
|
|
98
|
+
this.terminal.resize(cols, this.terminal.rows);
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Extract the rendered lines from the terminal buffer.
|
|
102
|
+
* This returns the actual visible content after all ANSI sequences
|
|
103
|
+
* have been processed.
|
|
104
|
+
*/ _proto.getLines = function getLines() {
|
|
105
|
+
var buffer = this.terminal.buffer.active;
|
|
106
|
+
var lines = [];
|
|
107
|
+
for(var i = 0; i < buffer.length; i++){
|
|
108
|
+
var line = buffer.getLine(i);
|
|
109
|
+
if (line) {
|
|
110
|
+
// translateToString(trimRight) - trim trailing whitespace
|
|
111
|
+
// Also trim leading whitespace - tools like ncu/npm use cursor positioning
|
|
112
|
+
// which creates lines with leading spaces when interpreted by xterm
|
|
113
|
+
lines.push(line.translateToString(true).trimStart());
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Trim trailing empty lines
|
|
117
|
+
while(lines.length > 0 && lines[lines.length - 1] === ''){
|
|
118
|
+
lines.pop();
|
|
119
|
+
}
|
|
120
|
+
return lines;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Clean up terminal resources.
|
|
124
|
+
*/ _proto.dispose = function dispose() {
|
|
125
|
+
this.terminal.dispose();
|
|
126
|
+
};
|
|
127
|
+
_create_class(TerminalBuffer, [
|
|
128
|
+
{
|
|
129
|
+
key: "lineCount",
|
|
130
|
+
get: /**
|
|
131
|
+
* Get the number of rendered lines.
|
|
132
|
+
*/ function get() {
|
|
133
|
+
return this.getLines().length;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
]);
|
|
137
|
+
return TerminalBuffer;
|
|
138
|
+
}();
|
|
139
|
+
/* 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/lib/TerminalBuffer.ts"],"sourcesContent":["import * as xterm from '@xterm/headless';\n\n// Handle both ESM and CJS module formats\nconst Terminal = (xterm as { Terminal: typeof xterm.Terminal; default?: { Terminal: typeof xterm.Terminal } }).Terminal || (xterm as { default?: { Terminal: typeof xterm.Terminal } }).default?.Terminal;\n\n/**\n * Wrapper around @xterm/headless Terminal that provides a virtual terminal buffer.\n * Interprets ANSI escape sequences (cursor movement, line clearing, etc.) to produce\n * the actual rendered output rather than raw intermediate states.\n */\nexport class TerminalBuffer {\n private terminal: InstanceType<typeof Terminal>;\n\n constructor(cols: number, scrollback = 10000) {\n this.terminal = new Terminal({\n cols,\n rows: 50, // Visible rows (doesn't matter much for headless)\n scrollback,\n allowProposedApi: true,\n });\n }\n\n /**\n * Write raw data to the terminal buffer.\n * The terminal interprets all ANSI sequences automatically.\n */\n write(data: string | Buffer): void {\n const str = typeof data === 'string' ? data : data.toString('utf8');\n this.terminal.write(str);\n }\n\n /**\n * Resize the terminal width.\n */\n resize(cols: number): void {\n this.terminal.resize(cols, this.terminal.rows);\n }\n\n /**\n * Extract the rendered lines from the terminal buffer.\n * This returns the actual visible content after all ANSI sequences\n * have been processed.\n */\n getLines(): string[] {\n const buffer = this.terminal.buffer.active;\n const lines: string[] = [];\n\n for (let i = 0; i < buffer.length; i++) {\n const line = buffer.getLine(i);\n if (line) {\n // translateToString(trimRight) - trim trailing whitespace\n // Also trim leading whitespace - tools like ncu/npm use cursor positioning\n // which creates lines with leading spaces when interpreted by xterm\n lines.push(line.translateToString(true).trimStart());\n }\n }\n\n // Trim trailing empty lines\n while (lines.length > 0 && lines[lines.length - 1] === '') {\n lines.pop();\n }\n\n return lines;\n }\n\n /**\n * Get the number of rendered lines.\n */\n get lineCount(): number {\n return this.getLines().length;\n }\n\n /**\n * Clean up terminal resources.\n */\n dispose(): void {\n this.terminal.dispose();\n }\n}\n"],"names":["TerminalBuffer","Terminal","xterm","default","cols","scrollback","terminal","rows","allowProposedApi","write","data","str","toString","resize","getLines","buffer","active","lines","i","length","line","getLine","push","translateToString","trimStart","pop","dispose","lineCount"],"mappings":";;;;+BAUaA;;;eAAAA;;;gEAVU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGoG;AAD3H,yCAAyC;AACzC,IAAMC,WAAW,AAACC,UAA6FD,QAAQ,MAAI,iBAAA,AAACC,UAA4DC,OAAO,cAApE,qCAAA,eAAsEF,QAAQ;AAOlM,IAAA,AAAMD,+BAAN;;aAAMA,eAGCI,IAAY;YAAEC,aAAAA,iEAAa;gCAH5BL;QAIT,IAAI,CAACM,QAAQ,GAAG,IAAIL,SAAS;YAC3BG,MAAAA;YACAG,MAAM;YACNF,YAAAA;YACAG,kBAAkB;QACpB;;iBATSR;IAYX;;;GAGC,GACDS,OAAAA,KAGC,GAHDA,SAAAA,MAAMC,IAAqB;QACzB,IAAMC,MAAM,OAAOD,SAAS,WAAWA,OAAOA,KAAKE,QAAQ,CAAC;QAC5D,IAAI,CAACN,QAAQ,CAACG,KAAK,CAACE;IACtB;IAEA;;GAEC,GACDE,OAAAA,MAEC,GAFDA,SAAAA,OAAOT,IAAY;QACjB,IAAI,CAACE,QAAQ,CAACO,MAAM,CAACT,MAAM,IAAI,CAACE,QAAQ,CAACC,IAAI;IAC/C;IAEA;;;;GAIC,GACDO,OAAAA,QAoBC,GApBDA,SAAAA;QACE,IAAMC,SAAS,IAAI,CAACT,QAAQ,CAACS,MAAM,CAACC,MAAM;QAC1C,IAAMC,QAAkB,EAAE;QAE1B,IAAK,IAAIC,IAAI,GAAGA,IAAIH,OAAOI,MAAM,EAAED,IAAK;YACtC,IAAME,OAAOL,OAAOM,OAAO,CAACH;YAC5B,IAAIE,MAAM;gBACR,0DAA0D;gBAC1D,2EAA2E;gBAC3E,oEAAoE;gBACpEH,MAAMK,IAAI,CAACF,KAAKG,iBAAiB,CAAC,MAAMC,SAAS;YACnD;QACF;QAEA,4BAA4B;QAC5B,MAAOP,MAAME,MAAM,GAAG,KAAKF,KAAK,CAACA,MAAME,MAAM,GAAG,EAAE,KAAK,GAAI;YACzDF,MAAMQ,GAAG;QACX;QAEA,OAAOR;IACT;IASA;;GAEC,GACDS,OAAAA,OAEC,GAFDA,SAAAA;QACE,IAAI,CAACpB,QAAQ,CAACoB,OAAO;IACvB;kBAnEW1B;;YA0DP2B,KAAAA;iBAAJ,AAHA;;GAEC,GACD;gBACE,OAAO,IAAI,CAACb,QAAQ,GAAGK,MAAM;YAC/B;;;WA5DWnB"}
|
package/dist/cjs/session.js
CHANGED
|
@@ -16,16 +16,28 @@ var _onone = /*#__PURE__*/ _interop_require_default(require("on-one"));
|
|
|
16
16
|
var _queuecb = /*#__PURE__*/ _interop_require_default(require("queue-cb"));
|
|
17
17
|
var _Appts = /*#__PURE__*/ _interop_require_default(require("./components/App.js"));
|
|
18
18
|
var _constantsts = require("./constants.js");
|
|
19
|
-
var _addLinests = /*#__PURE__*/ _interop_require_default(require("./lib/addLines.js"));
|
|
20
19
|
var _concatWritablets = /*#__PURE__*/ _interop_require_default(require("./lib/concatWritable.js"));
|
|
21
20
|
var _formatArgumentsts = /*#__PURE__*/ _interop_require_default(require("./lib/formatArguments.js"));
|
|
21
|
+
var _TerminalBufferts = require("./lib/TerminalBuffer.js");
|
|
22
22
|
var _processStorets = require("./state/processStore.js");
|
|
23
|
-
var _typests = require("./types.js");
|
|
24
23
|
function _class_call_check(instance, Constructor) {
|
|
25
24
|
if (!(instance instanceof Constructor)) {
|
|
26
25
|
throw new TypeError("Cannot call a class as a function");
|
|
27
26
|
}
|
|
28
27
|
}
|
|
28
|
+
function _define_property(obj, key, value) {
|
|
29
|
+
if (key in obj) {
|
|
30
|
+
Object.defineProperty(obj, key, {
|
|
31
|
+
value: value,
|
|
32
|
+
enumerable: true,
|
|
33
|
+
configurable: true,
|
|
34
|
+
writable: true
|
|
35
|
+
});
|
|
36
|
+
} else {
|
|
37
|
+
obj[key] = value;
|
|
38
|
+
}
|
|
39
|
+
return obj;
|
|
40
|
+
}
|
|
29
41
|
function _interop_require_default(obj) {
|
|
30
42
|
return obj && obj.__esModule ? obj : {
|
|
31
43
|
default: obj
|
|
@@ -72,6 +84,45 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
72
84
|
}
|
|
73
85
|
return newObj;
|
|
74
86
|
}
|
|
87
|
+
function _object_spread(target) {
|
|
88
|
+
for(var i = 1; i < arguments.length; i++){
|
|
89
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
90
|
+
var ownKeys = Object.keys(source);
|
|
91
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
92
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
93
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
ownKeys.forEach(function(key) {
|
|
97
|
+
_define_property(target, key, source[key]);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return target;
|
|
101
|
+
}
|
|
102
|
+
function ownKeys(object, enumerableOnly) {
|
|
103
|
+
var keys = Object.keys(object);
|
|
104
|
+
if (Object.getOwnPropertySymbols) {
|
|
105
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
106
|
+
if (enumerableOnly) {
|
|
107
|
+
symbols = symbols.filter(function(sym) {
|
|
108
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
keys.push.apply(keys, symbols);
|
|
112
|
+
}
|
|
113
|
+
return keys;
|
|
114
|
+
}
|
|
115
|
+
function _object_spread_props(target, source) {
|
|
116
|
+
source = source != null ? source : {};
|
|
117
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
118
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
119
|
+
} else {
|
|
120
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
121
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return target;
|
|
125
|
+
}
|
|
75
126
|
function _object_without_properties(source, excluded) {
|
|
76
127
|
if (source == null) return {};
|
|
77
128
|
var target = _object_without_properties_loose(source, excluded);
|
|
@@ -111,13 +162,21 @@ var SessionImpl = /*#__PURE__*/ function() {
|
|
|
111
162
|
this.store = new _processStorets.ProcessStore(options);
|
|
112
163
|
var _options_interactive;
|
|
113
164
|
this.isInteractive = (_options_interactive = options.interactive) !== null && _options_interactive !== void 0 ? _options_interactive : false;
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
165
|
+
// Use a very wide buffer to prevent line wrapping in xterm
|
|
166
|
+
// Actual display truncation is handled by Ink components
|
|
167
|
+
this.terminalWidth = 10000;
|
|
168
|
+
// Only render Ink when stdout is a real terminal
|
|
169
|
+
// When piped (e.g., nested spawn-term), skip Ink to avoid cursor positioning artifacts
|
|
170
|
+
if (process.stdout.isTTY) {
|
|
171
|
+
// Note: incrementalRendering disabled to prevent corruption when content shifts vertically
|
|
172
|
+
// (e.g., error footer appearing, processes completing, scroll position changes)
|
|
173
|
+
this.inkApp = (0, _ink.render)(/*#__PURE__*/ (0, _jsxruntime.jsx)(_Appts.default, {
|
|
174
|
+
store: this.store
|
|
175
|
+
}), {
|
|
176
|
+
incrementalRendering: false,
|
|
177
|
+
maxFps: _constantsts.DEFAULT_MAX_FPS
|
|
178
|
+
});
|
|
179
|
+
}
|
|
121
180
|
}
|
|
122
181
|
var _proto = SessionImpl.prototype;
|
|
123
182
|
_proto.spawn = function spawn(command, args, spawnOptions, options, callback) {
|
|
@@ -130,8 +189,28 @@ var SessionImpl = /*#__PURE__*/ function() {
|
|
|
130
189
|
"stdio"
|
|
131
190
|
]);
|
|
132
191
|
if (stdio === 'inherit') {
|
|
192
|
+
// When Ink is not rendering (stdout not a TTY), pass output directly to stdout
|
|
193
|
+
if (!this.inkApp) {
|
|
194
|
+
var cp = (0, _crossspawncb.crossSpawn)(command, args, _object_spread_props(_object_spread({}, csOptions), {
|
|
195
|
+
stdio: 'inherit'
|
|
196
|
+
}));
|
|
197
|
+
_crossspawncb.default.worker(cp, csOptions, function(err) {
|
|
198
|
+
var res = err ? err : {};
|
|
199
|
+
res.stdout = null;
|
|
200
|
+
res.stderr = null;
|
|
201
|
+
res.output = [
|
|
202
|
+
null,
|
|
203
|
+
null,
|
|
204
|
+
null
|
|
205
|
+
];
|
|
206
|
+
err ? callback(err) : callback(null, res);
|
|
207
|
+
});
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
133
210
|
this.runningCount++;
|
|
134
211
|
var id = _crypto.default.randomUUID();
|
|
212
|
+
// Create terminal buffer for ANSI sequence interpretation
|
|
213
|
+
var terminalBuffer = new _TerminalBufferts.TerminalBuffer(this.terminalWidth);
|
|
135
214
|
this.store.addProcess({
|
|
136
215
|
id: id,
|
|
137
216
|
title: [
|
|
@@ -139,55 +218,49 @@ var SessionImpl = /*#__PURE__*/ function() {
|
|
|
139
218
|
].concat((0, _formatArgumentsts.default)(args)).join(' '),
|
|
140
219
|
state: 'running',
|
|
141
220
|
lines: [],
|
|
221
|
+
terminalBuffer: terminalBuffer,
|
|
142
222
|
group: options.group,
|
|
143
223
|
expanded: options.expanded
|
|
144
224
|
});
|
|
145
|
-
var
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
outputs.stdout = (0, _addLinests.default)(function(lines) {
|
|
153
|
-
_this.store.appendLines(id, lines.map(function(text) {
|
|
154
|
-
return {
|
|
155
|
-
type: _typests.LineType.stdout,
|
|
156
|
-
text: text
|
|
157
|
-
};
|
|
158
|
-
}));
|
|
225
|
+
var cp1 = (0, _crossspawncb.crossSpawn)(command, args, csOptions);
|
|
226
|
+
// Pipe stdout and stderr directly to terminal buffer
|
|
227
|
+
// Both streams go to the same buffer to maintain correct ordering
|
|
228
|
+
if (cp1.stdout) {
|
|
229
|
+
cp1.stdout.on('data', function(chunk) {
|
|
230
|
+
terminalBuffer.write(chunk);
|
|
231
|
+
_this.store.notify();
|
|
159
232
|
});
|
|
160
|
-
|
|
233
|
+
}
|
|
234
|
+
if (cp1.stderr) {
|
|
235
|
+
cp1.stderr.on('data', function(chunk) {
|
|
236
|
+
terminalBuffer.write(chunk);
|
|
237
|
+
_this.store.notify();
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
// Wait for process to complete
|
|
241
|
+
var queue = new _queuecb.default();
|
|
242
|
+
if (cp1.stdout) {
|
|
243
|
+
queue.defer(_onone.default.bind(null, cp1.stdout, [
|
|
161
244
|
'error',
|
|
162
245
|
'end',
|
|
163
|
-
'close'
|
|
164
|
-
'finish'
|
|
246
|
+
'close'
|
|
165
247
|
]));
|
|
166
248
|
}
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
_this.store.appendLines(id, lines.map(function(text) {
|
|
170
|
-
return {
|
|
171
|
-
type: _typests.LineType.stderr,
|
|
172
|
-
text: text
|
|
173
|
-
};
|
|
174
|
-
}));
|
|
175
|
-
});
|
|
176
|
-
queue.defer(_onone.default.bind(null, cp.stderr.pipe(outputs.stderr), [
|
|
249
|
+
if (cp1.stderr) {
|
|
250
|
+
queue.defer(_onone.default.bind(null, cp1.stderr, [
|
|
177
251
|
'error',
|
|
178
252
|
'end',
|
|
179
|
-
'close'
|
|
180
|
-
'finish'
|
|
253
|
+
'close'
|
|
181
254
|
]));
|
|
182
255
|
}
|
|
183
|
-
queue.defer(_crossspawncb.default.worker.bind(null,
|
|
256
|
+
queue.defer(_crossspawncb.default.worker.bind(null, cp1, csOptions));
|
|
184
257
|
queue.await(function(err) {
|
|
185
258
|
var res = err ? err : {};
|
|
186
|
-
res.stdout =
|
|
187
|
-
res.stderr =
|
|
259
|
+
res.stdout = null; // Not collecting raw output in inherit mode
|
|
260
|
+
res.stderr = null;
|
|
188
261
|
res.output = [
|
|
189
|
-
|
|
190
|
-
|
|
262
|
+
null,
|
|
263
|
+
null,
|
|
191
264
|
null
|
|
192
265
|
];
|
|
193
266
|
_this.store.updateProcess(id, {
|
|
@@ -198,39 +271,39 @@ var SessionImpl = /*#__PURE__*/ function() {
|
|
|
198
271
|
});
|
|
199
272
|
} else {
|
|
200
273
|
// Non-inherit mode: collect output but don't display in UI
|
|
201
|
-
var
|
|
202
|
-
var
|
|
274
|
+
var cp2 = (0, _crossspawncb.crossSpawn)(command, args, csOptions);
|
|
275
|
+
var outputs = {
|
|
203
276
|
stdout: null,
|
|
204
277
|
stderr: null
|
|
205
278
|
};
|
|
206
279
|
var queue1 = new _queuecb.default();
|
|
207
|
-
if (
|
|
208
|
-
|
|
209
|
-
|
|
280
|
+
if (cp2.stdout) {
|
|
281
|
+
outputs.stdout = (0, _concatWritablets.default)(function(output) {
|
|
282
|
+
outputs.stdout.output = output.toString(encoding || 'utf8');
|
|
210
283
|
});
|
|
211
|
-
queue1.defer(_onone.default.bind(null,
|
|
284
|
+
queue1.defer(_onone.default.bind(null, cp2.stdout.pipe(outputs.stdout), [
|
|
212
285
|
'error',
|
|
213
286
|
'end',
|
|
214
287
|
'close',
|
|
215
288
|
'finish'
|
|
216
289
|
]));
|
|
217
290
|
}
|
|
218
|
-
if (
|
|
219
|
-
|
|
220
|
-
|
|
291
|
+
if (cp2.stderr) {
|
|
292
|
+
outputs.stderr = (0, _concatWritablets.default)(function(output) {
|
|
293
|
+
outputs.stderr.output = output.toString(encoding || 'utf8');
|
|
221
294
|
});
|
|
222
|
-
queue1.defer(_onone.default.bind(null,
|
|
295
|
+
queue1.defer(_onone.default.bind(null, cp2.stderr.pipe(outputs.stderr), [
|
|
223
296
|
'error',
|
|
224
297
|
'end',
|
|
225
298
|
'close',
|
|
226
299
|
'finish'
|
|
227
300
|
]));
|
|
228
301
|
}
|
|
229
|
-
queue1.defer(_crossspawncb.default.worker.bind(null,
|
|
302
|
+
queue1.defer(_crossspawncb.default.worker.bind(null, cp2, csOptions));
|
|
230
303
|
queue1.await(function(err) {
|
|
231
304
|
var res = err ? err : {};
|
|
232
|
-
res.stdout =
|
|
233
|
-
res.stderr =
|
|
305
|
+
res.stdout = outputs.stdout ? outputs.stdout.output : null;
|
|
306
|
+
res.stderr = outputs.stderr ? outputs.stderr.output : null;
|
|
234
307
|
res.output = [
|
|
235
308
|
res.stdout,
|
|
236
309
|
res.stderr,
|
package/dist/cjs/session.js.map
CHANGED
|
@@ -1 +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 private isInteractive: boolean;\n\n constructor(options: SessionOptions = {}) {\n this.store = new ProcessStore(options);\n this.isInteractive = options.interactive ?? false;\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 (callback) this.waitCallbacks.push(callback);\n\n if (this.runningCount === 0) {\n if (this.isInteractive) {\n // In interactive mode, wait for user to quit (press 'q')\n const unsubscribe = this.store.subscribe(() => {\n if (this.store.getShouldExit()) {\n unsubscribe();\n this.closeAndCallWaitCallbacks();\n }\n });\n } else {\n this.closeAndCallWaitCallbacks();\n }\n }\n // If runningCount > 0, will close when it hits 0 in onProcessComplete\n }\n\n private onProcessComplete(): void {\n this.runningCount--;\n if (this.runningCount === 0 && this.waitCallbacks.length > 0) {\n if (this.isInteractive) {\n // In interactive mode, wait for user to quit (press 'q')\n const unsubscribe = this.store.subscribe(() => {\n if (this.store.getShouldExit()) {\n unsubscribe();\n this.closeAndCallWaitCallbacks();\n }\n });\n } else {\n this.closeAndCallWaitCallbacks();\n }\n }\n }\n\n private closeAndCallWaitCallbacks(): void {\n if (this.closed) return;\n this.closed = true;\n this.cleanup(() => {\n for (const cb of this.waitCallbacks) cb();\n this.waitCallbacks = [];\n });\n }\n\n private cleanup(onComplete?: () => void): 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 onComplete?.();\n })\n .catch(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n onComplete?.();\n });\n this.inkApp = null;\n } else {\n onComplete?.();\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","isInteractive","interactive","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","unsubscribe","subscribe","getShouldExit","closeAndCallWaitCallbacks","length","cb","onComplete","signalExit","reset","process","write","waitUntilExit","then","getExitCallback","catch"],"mappings":"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"}
|
|
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 concatWritable from './lib/concatWritable.ts';\nimport formatArguments from './lib/formatArguments.ts';\nimport { TerminalBuffer } from './lib/TerminalBuffer.ts';\nimport { ProcessStore } from './state/processStore.ts';\nimport type { ProcessOptions, SessionOptions, SpawnError, SpawnOptions, TerminalCallback } 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 private isInteractive: boolean;\n private terminalWidth: number;\n\n constructor(options: SessionOptions = {}) {\n this.store = new ProcessStore(options);\n this.isInteractive = options.interactive ?? false;\n // Use a very wide buffer to prevent line wrapping in xterm\n // Actual display truncation is handled by Ink components\n this.terminalWidth = 10000;\n\n // Only render Ink when stdout is a real terminal\n // When piped (e.g., nested spawn-term), skip Ink to avoid cursor positioning artifacts\n if (process.stdout.isTTY) {\n // Note: incrementalRendering disabled to prevent corruption when content shifts vertically\n // (e.g., error footer appearing, processes completing, scroll position changes)\n this.inkApp = render(<App store={this.store} />, {\n incrementalRendering: false,\n maxFps: DEFAULT_MAX_FPS,\n });\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 // When Ink is not rendering (stdout not a TTY), pass output directly to stdout\n if (!this.inkApp) {\n const cp = crossSpawn(command, args, { ...csOptions, stdio: 'inherit' });\n spawn.worker(cp, csOptions, (err?: SpawnError) => {\n const res = (err ? err : {}) as SpawnResult;\n res.stdout = null;\n res.stderr = null;\n res.output = [null, null, null];\n err ? callback(err) : callback(null, res);\n });\n return;\n }\n\n this.runningCount++;\n const id = crypto.randomUUID();\n\n // Create terminal buffer for ANSI sequence interpretation\n const terminalBuffer = new TerminalBuffer(this.terminalWidth);\n\n this.store.addProcess({\n id,\n title: [command].concat(formatArguments(args)).join(' '),\n state: 'running',\n lines: [],\n terminalBuffer,\n group: options.group,\n expanded: options.expanded,\n });\n\n const cp = crossSpawn(command, args, csOptions);\n\n // Pipe stdout and stderr directly to terminal buffer\n // Both streams go to the same buffer to maintain correct ordering\n if (cp.stdout) {\n cp.stdout.on('data', (chunk: Buffer) => {\n terminalBuffer.write(chunk);\n this.store.notify();\n });\n }\n if (cp.stderr) {\n cp.stderr.on('data', (chunk: Buffer) => {\n terminalBuffer.write(chunk);\n this.store.notify();\n });\n }\n\n // Wait for process to complete\n const queue = new Queue();\n if (cp.stdout) {\n queue.defer(oo.bind(null, cp.stdout, ['error', 'end', 'close']));\n }\n if (cp.stderr) {\n queue.defer(oo.bind(null, cp.stderr, ['error', 'end', 'close']));\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 = null; // Not collecting raw output in inherit mode\n res.stderr = null;\n res.output = [null, null, 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 (callback) this.waitCallbacks.push(callback);\n\n if (this.runningCount === 0) {\n if (this.isInteractive) {\n // In interactive mode, wait for user to quit (press 'q')\n const unsubscribe = this.store.subscribe(() => {\n if (this.store.getShouldExit()) {\n unsubscribe();\n this.closeAndCallWaitCallbacks();\n }\n });\n } else {\n this.closeAndCallWaitCallbacks();\n }\n }\n // If runningCount > 0, will close when it hits 0 in onProcessComplete\n }\n\n private onProcessComplete(): void {\n this.runningCount--;\n if (this.runningCount === 0 && this.waitCallbacks.length > 0) {\n if (this.isInteractive) {\n // In interactive mode, wait for user to quit (press 'q')\n const unsubscribe = this.store.subscribe(() => {\n if (this.store.getShouldExit()) {\n unsubscribe();\n this.closeAndCallWaitCallbacks();\n }\n });\n } else {\n this.closeAndCallWaitCallbacks();\n }\n }\n }\n\n private closeAndCallWaitCallbacks(): void {\n if (this.closed) return;\n this.closed = true;\n this.cleanup(() => {\n for (const cb of this.waitCallbacks) cb();\n this.waitCallbacks = [];\n });\n }\n\n private cleanup(onComplete?: () => void): 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 onComplete?.();\n })\n .catch(() => {\n const cb = this.store.getExitCallback();\n cb?.();\n onComplete?.();\n });\n this.inkApp = null;\n } else {\n onComplete?.();\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","isInteractive","interactive","terminalWidth","process","stdout","isTTY","render","App","incrementalRendering","maxFps","DEFAULT_MAX_FPS","spawn","command","args","spawnOptions","callback","Error","encoding","stdio","csOptions","cp","crossSpawn","worker","err","res","stderr","output","id","crypto","randomUUID","terminalBuffer","TerminalBuffer","addProcess","title","concat","formatArguments","join","state","lines","group","expanded","on","chunk","write","notify","queue","Queue","defer","oo","bind","await","updateProcess","onProcessComplete","outputs","concatWritable","toString","pipe","close","cleanup","waitAndClose","push","unsubscribe","subscribe","getShouldExit","closeAndCallWaitCallbacks","length","cb","onComplete","signalExit","reset","waitUntilExit","then","getExitCallback","catch"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Line } from '../types.js';
|
|
2
|
+
type ErrorGroup = {
|
|
3
|
+
processName: string;
|
|
4
|
+
lines: Line[];
|
|
5
|
+
};
|
|
6
|
+
type Props = {
|
|
7
|
+
errors: ErrorGroup[];
|
|
8
|
+
isExpanded: boolean;
|
|
9
|
+
};
|
|
10
|
+
declare const _default: import("react").NamedExoticComponent<Props>;
|
|
11
|
+
export default _default;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { default as figures } from './lib/figures.js';
|
|
2
2
|
export { default as formatArguments } from './lib/formatArguments.js';
|
|
3
|
+
export { TerminalBuffer } from './lib/TerminalBuffer.js';
|
|
3
4
|
export * from './types.js';
|
|
4
5
|
import type { createSession as createSessionType, Session } from './createSessionWrapper.js';
|
|
5
6
|
export type { Session };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrapper around @xterm/headless Terminal that provides a virtual terminal buffer.
|
|
3
|
+
* Interprets ANSI escape sequences (cursor movement, line clearing, etc.) to produce
|
|
4
|
+
* the actual rendered output rather than raw intermediate states.
|
|
5
|
+
*/
|
|
6
|
+
export declare class TerminalBuffer {
|
|
7
|
+
private terminal;
|
|
8
|
+
constructor(cols: number, scrollback?: number);
|
|
9
|
+
/**
|
|
10
|
+
* Write raw data to the terminal buffer.
|
|
11
|
+
* The terminal interprets all ANSI sequences automatically.
|
|
12
|
+
*/
|
|
13
|
+
write(data: string | Buffer): void;
|
|
14
|
+
/**
|
|
15
|
+
* Resize the terminal width.
|
|
16
|
+
*/
|
|
17
|
+
resize(cols: number): void;
|
|
18
|
+
/**
|
|
19
|
+
* Extract the rendered lines from the terminal buffer.
|
|
20
|
+
* This returns the actual visible content after all ANSI sequences
|
|
21
|
+
* have been processed.
|
|
22
|
+
*/
|
|
23
|
+
getLines(): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Get the number of rendered lines.
|
|
26
|
+
*/
|
|
27
|
+
get lineCount(): number;
|
|
28
|
+
/**
|
|
29
|
+
* Clean up terminal resources.
|
|
30
|
+
*/
|
|
31
|
+
dispose(): void;
|
|
32
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ChildProcess, Line, SessionOptions } from '../types.js';
|
|
2
2
|
type Listener = () => void;
|
|
3
|
-
type Mode = 'normal' | 'interactive'
|
|
3
|
+
type Mode = 'normal' | 'interactive';
|
|
4
4
|
export declare class ProcessStore {
|
|
5
5
|
private processes;
|
|
6
6
|
private completedIds;
|
|
@@ -9,10 +9,11 @@ export declare class ProcessStore {
|
|
|
9
9
|
private exitCallback;
|
|
10
10
|
private mode;
|
|
11
11
|
private selectedIndex;
|
|
12
|
-
private selectedErrorIndex;
|
|
13
12
|
private expandedId;
|
|
14
13
|
private scrollOffset;
|
|
15
14
|
private listScrollOffset;
|
|
15
|
+
private errorFooterExpanded;
|
|
16
|
+
private bufferVersion;
|
|
16
17
|
private header;
|
|
17
18
|
private showStatusBar;
|
|
18
19
|
private isInteractive;
|
|
@@ -29,10 +30,11 @@ export declare class ProcessStore {
|
|
|
29
30
|
getErrorLineCount: () => number;
|
|
30
31
|
getMode: () => Mode;
|
|
31
32
|
getSelectedIndex: () => number;
|
|
32
|
-
getSelectedErrorIndex: () => number;
|
|
33
33
|
getExpandedId: () => string | null;
|
|
34
34
|
getScrollOffset: () => number;
|
|
35
35
|
getListScrollOffset: () => number;
|
|
36
|
+
getErrorFooterExpanded: () => boolean;
|
|
37
|
+
getBufferVersion: () => number;
|
|
36
38
|
getHeader: () => string | undefined;
|
|
37
39
|
getShowStatusBar: () => boolean;
|
|
38
40
|
getIsInteractive: () => boolean;
|
|
@@ -41,14 +43,19 @@ export declare class ProcessStore {
|
|
|
41
43
|
updateProcess(id: string, update: Partial<ChildProcess>): void;
|
|
42
44
|
appendLines(id: string, newLines: Line[]): void;
|
|
43
45
|
getProcess(id: string): ChildProcess | undefined;
|
|
46
|
+
getProcessLines(id: string): Line[];
|
|
47
|
+
getProcessLineCount(id: string): number;
|
|
44
48
|
setMode(mode: Mode): void;
|
|
45
49
|
selectNext(visibleCount?: number): void;
|
|
46
50
|
selectPrev(visibleCount?: number): void;
|
|
47
51
|
private adjustListScroll;
|
|
48
52
|
getSelectedProcess(): ChildProcess | undefined;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
toggleErrorFooter(): void;
|
|
54
|
+
expandErrorFooter(): void;
|
|
55
|
+
getErrorLines(): Array<{
|
|
56
|
+
processName: string;
|
|
57
|
+
lines: Line[];
|
|
58
|
+
}>;
|
|
52
59
|
toggleExpand(): void;
|
|
53
60
|
collapse(): void;
|
|
54
61
|
scrollDown(maxVisible: number): void;
|
|
@@ -57,6 +64,6 @@ export declare class ProcessStore {
|
|
|
57
64
|
getShouldExit: () => boolean;
|
|
58
65
|
getExitCallback: () => (() => void) | null;
|
|
59
66
|
reset(): void;
|
|
60
|
-
|
|
67
|
+
notify(): void;
|
|
61
68
|
}
|
|
62
69
|
export {};
|
package/dist/cjs/src/types.d.ts
CHANGED
|
@@ -19,11 +19,13 @@ export type Line = {
|
|
|
19
19
|
text: string;
|
|
20
20
|
};
|
|
21
21
|
export type State = 'running' | 'error' | 'success';
|
|
22
|
+
import type { TerminalBuffer } from './lib/TerminalBuffer.js';
|
|
22
23
|
export type ChildProcess = {
|
|
23
24
|
id: string;
|
|
24
25
|
group?: string;
|
|
25
26
|
title: string;
|
|
26
27
|
state: State;
|
|
27
28
|
lines: Line[];
|
|
29
|
+
terminalBuffer?: TerminalBuffer;
|
|
28
30
|
expanded?: boolean;
|
|
29
31
|
};
|