spawn-term 3.3.5 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/compat.js +32 -4
- package/dist/cjs/compat.js.map +1 -1
- package/dist/cjs/lib/addLines.js.map +1 -1
- package/dist/cjs/lib/concatWritable.js +2 -8
- package/dist/cjs/lib/concatWritable.js.map +1 -1
- package/dist/cjs/lib/loadInk.js +2 -2
- package/dist/cjs/lib/loadInk.js.map +1 -1
- package/dist/cjs/session.js +18 -9
- package/dist/cjs/session.js.map +1 -1
- package/dist/cjs/src/compat.d.ts +4 -0
- package/dist/cjs/src/lib/addLines.d.ts +1 -1
- package/dist/cjs/src/lib/concatWritable.d.ts +1 -1
- package/dist/cjs/state/processStore.js +3 -4
- package/dist/cjs/state/processStore.js.map +1 -1
- package/dist/esm/compat.js +12 -1
- package/dist/esm/compat.js.map +1 -1
- package/dist/esm/lib/addLines.js.map +1 -1
- package/dist/esm/lib/concatWritable.js +1 -2
- package/dist/esm/lib/concatWritable.js.map +1 -1
- package/dist/esm/session.js +1 -1
- package/dist/esm/session.js.map +1 -1
- package/dist/esm/src/compat.d.ts +4 -0
- package/dist/esm/src/lib/addLines.d.ts +1 -1
- package/dist/esm/src/lib/concatWritable.d.ts +1 -1
- package/dist/esm/state/processStore.js +3 -4
- package/dist/esm/state/processStore.js.map +1 -1
- package/package.json +11 -11
package/dist/cjs/compat.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility Layer for Node.js 0.8+
|
|
3
|
+
* Local to this package - contains only needed functions.
|
|
4
|
+
*/ "use strict";
|
|
2
5
|
Object.defineProperty(exports, "__esModule", {
|
|
3
6
|
value: true
|
|
4
7
|
});
|
|
@@ -9,6 +12,18 @@ function _export(target, all) {
|
|
|
9
12
|
});
|
|
10
13
|
}
|
|
11
14
|
_export(exports, {
|
|
15
|
+
get PassThrough () {
|
|
16
|
+
return PassThrough;
|
|
17
|
+
},
|
|
18
|
+
get Readable () {
|
|
19
|
+
return Readable;
|
|
20
|
+
},
|
|
21
|
+
get Transform () {
|
|
22
|
+
return Transform;
|
|
23
|
+
},
|
|
24
|
+
get Writable () {
|
|
25
|
+
return Writable;
|
|
26
|
+
},
|
|
12
27
|
get arrayFind () {
|
|
13
28
|
return arrayFind;
|
|
14
29
|
},
|
|
@@ -16,10 +31,23 @@ _export(exports, {
|
|
|
16
31
|
return stringEndsWith;
|
|
17
32
|
}
|
|
18
33
|
});
|
|
34
|
+
var _module = /*#__PURE__*/ _interop_require_default(require("module"));
|
|
35
|
+
function _interop_require_default(obj) {
|
|
36
|
+
return obj && obj.__esModule ? obj : {
|
|
37
|
+
default: obj
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
var _require = typeof require === 'undefined' ? _module.default.createRequire(require("url").pathToFileURL(__filename).toString()) : require;
|
|
41
|
+
/**
|
|
42
|
+
* Stream compatibility - Transform class
|
|
43
|
+
* - Uses native stream.Transform on Node 0.10+
|
|
44
|
+
* - Falls back to readable-stream for Node 0.8
|
|
45
|
+
*/ var major = +process.versions.node.split('.')[0];
|
|
46
|
+
var Readable = major > 0 ? _require('stream').Readable : _require('readable-stream').Readable;
|
|
47
|
+
var Writable = major > 0 ? _require('stream').Writable : _require('readable-stream').Writable;
|
|
48
|
+
var Transform = major > 0 ? _require('stream').Transform : _require('readable-stream').Transform;
|
|
49
|
+
var PassThrough = major > 0 ? _require('stream').PassThrough : _require('readable-stream').PassThrough;
|
|
19
50
|
/**
|
|
20
|
-
* Compatibility Layer for Node.js 0.8+
|
|
21
|
-
* Local to this package - contains only needed functions.
|
|
22
|
-
*/ /**
|
|
23
51
|
* String.prototype.endsWith wrapper for Node.js 0.8+
|
|
24
52
|
* - Uses native endsWith on Node 4.0+ / ES2015+
|
|
25
53
|
* - Falls back to lastIndexOf on Node 0.8-3.x
|
package/dist/cjs/compat.js.map
CHANGED
|
@@ -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 */\nconst hasEndsWith = typeof String.prototype.endsWith === 'function';\
|
|
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\nimport Module from 'module';\n\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\n\n/**\n * Stream compatibility - Transform class\n * - Uses native stream.Transform on Node 0.10+\n * - Falls back to readable-stream for Node 0.8\n */\nconst major = +process.versions.node.split('.')[0];\nexport const Readable: typeof import('stream').Readable = major > 0 ? _require('stream').Readable : _require('readable-stream').Readable;\nexport const Writable: typeof import('stream').Writable = major > 0 ? _require('stream').Writable : _require('readable-stream').Writable;\nexport const Transform: typeof import('stream').Transform = major > 0 ? _require('stream').Transform : _require('readable-stream').Transform;\nexport const PassThrough: typeof import('stream').PassThrough = major > 0 ? _require('stream').PassThrough : _require('readable-stream').PassThrough;\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 */\nconst hasEndsWith = typeof String.prototype.endsWith === 'function';\nexport function stringEndsWith(str: string, search: string, position?: number): boolean {\n if (hasEndsWith) {\n return str.endsWith(search, position);\n }\n const 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 */\nconst 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 (let i = 0; i < arr.length; i++) {\n if (predicate(arr[i], i, arr)) return arr[i];\n }\n return undefined;\n}\n"],"names":["PassThrough","Readable","Transform","Writable","arrayFind","stringEndsWith","_require","require","Module","createRequire","major","process","versions","node","split","hasEndsWith","String","prototype","endsWith","str","search","position","len","undefined","length","lastIndexOf","hasArrayFind","Array","find","arr","predicate","i"],"mappings":"AAAA;;;CAGC;;;;;;;;;;;QAeYA;eAAAA;;QAHAC;eAAAA;;QAEAC;eAAAA;;QADAC;eAAAA;;QAyBGC;eAAAA;;QAfAC;eAAAA;;;6DArBG;;;;;;AAEnB,IAAMC,WAAW,OAAOC,YAAY,cAAcC,eAAM,CAACC,aAAa,CAAC,uDAAmBF;AAE1F;;;;CAIC,GACD,IAAMG,QAAQ,CAACC,QAAQC,QAAQ,CAACC,IAAI,CAACC,KAAK,CAAC,IAAI,CAAC,EAAE;AAC3C,IAAMb,WAA6CS,QAAQ,IAAIJ,SAAS,UAAUL,QAAQ,GAAGK,SAAS,mBAAmBL,QAAQ;AACjI,IAAME,WAA6CO,QAAQ,IAAIJ,SAAS,UAAUH,QAAQ,GAAGG,SAAS,mBAAmBH,QAAQ;AACjI,IAAMD,YAA+CQ,QAAQ,IAAIJ,SAAS,UAAUJ,SAAS,GAAGI,SAAS,mBAAmBJ,SAAS;AACrI,IAAMF,cAAmDU,QAAQ,IAAIJ,SAAS,UAAUN,WAAW,GAAGM,SAAS,mBAAmBN,WAAW;AAEpJ;;;;CAIC,GACD,IAAMe,cAAc,OAAOC,OAAOC,SAAS,CAACC,QAAQ,KAAK;AAClD,SAASb,eAAec,GAAW,EAAEC,MAAc,EAAEC,QAAiB;IAC3E,IAAIN,aAAa;QACf,OAAOI,IAAID,QAAQ,CAACE,QAAQC;IAC9B;IACA,IAAMC,MAAMD,aAAaE,YAAYJ,IAAIK,MAAM,GAAGH;IAClD,OAAOF,IAAIM,WAAW,CAACL,YAAYE,MAAMF,OAAOI,MAAM;AACxD;AAEA;;;;CAIC,GACD,IAAME,eAAe,OAAOC,MAAMV,SAAS,CAACW,IAAI,KAAK;AAE9C,SAASxB,UAAayB,GAAQ,EAAEC,SAAwD;IAC7F,IAAIJ,cAAc;QAChB,OAAOG,IAAID,IAAI,CAACE;IAClB;IACA,IAAK,IAAIC,IAAI,GAAGA,IAAIF,IAAIL,MAAM,EAAEO,IAAK;QACnC,IAAID,UAAUD,GAAG,CAACE,EAAE,EAAEA,GAAGF,MAAM,OAAOA,GAAG,CAACE,EAAE;IAC9C;IACA,OAAOR;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/addLines.ts"],"sourcesContent":["import { Writable } from 'stream';\nimport { BATCH_MAX_LINES, BATCH_MAX_WAIT_MS } from '../constants.ts';\n\nconst REGEX_NEW_LINE = /\\r?\\n|\\r/g;\n\nexport type Callback = (lines: string[]) =>
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/addLines.ts"],"sourcesContent":["import { Writable } from 'stream';\nimport { BATCH_MAX_LINES, BATCH_MAX_WAIT_MS } from '../constants.ts';\n\nconst REGEX_NEW_LINE = /\\r?\\n|\\r/g;\n\nexport type Callback = (lines: string[]) => void;\n\ninterface BatchOptions {\n maxLines?: number;\n maxWait?: number;\n}\n\nexport default function addLines(fn: Callback, options: BatchOptions = {}): Writable {\n const { maxLines = BATCH_MAX_LINES, maxWait = BATCH_MAX_WAIT_MS } = options;\n\n let last = '';\n let lineBuffer: string[] = [];\n let flushTimer: NodeJS.Timeout | null = null;\n\n const flush = () => {\n if (flushTimer) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n if (lineBuffer.length > 0) {\n fn(lineBuffer);\n lineBuffer = [];\n }\n };\n\n const scheduleFlush = () => {\n if (!flushTimer) {\n flushTimer = setTimeout(flush, maxWait);\n }\n };\n\n const stream = new Writable({\n write(chunk, _enc, callback) {\n const more = last + chunk.toString('utf8');\n const lines = more.split(REGEX_NEW_LINE);\n last = lines.pop();\n\n if (lines.length > 0) {\n lineBuffer.push(...lines);\n\n // Flush immediately if buffer is large enough\n if (lineBuffer.length >= maxLines) {\n flush();\n } else {\n scheduleFlush();\n }\n }\n callback();\n },\n });\n\n stream.on('finish', () => {\n // Flush any remaining buffered lines\n if (last.length) lineBuffer.push(last);\n flush();\n last = '';\n });\n\n return stream;\n}\n"],"names":["addLines","REGEX_NEW_LINE","fn","options","maxLines","BATCH_MAX_LINES","maxWait","BATCH_MAX_WAIT_MS","last","lineBuffer","flushTimer","flush","clearTimeout","length","scheduleFlush","setTimeout","stream","Writable","write","chunk","_enc","callback","more","toString","lines","split","pop","push","on"],"mappings":";;;;+BAYA;;;eAAwBA;;;sBAZC;2BAC0B;;;;;;;;;;;;;;;;;;;;;;;;;;AAEnD,IAAMC,iBAAiB;AASR,SAASD,SAASE,EAAY;QAAEC,UAAAA,iEAAwB,CAAC;IACtE,wBAAoEA,QAA5DC,UAAAA,0CAAWC,4BAAe,yCAAkCF,QAAhCG,SAAAA,wCAAUC,8BAAiB;IAE/D,IAAIC,OAAO;IACX,IAAIC,aAAuB,EAAE;IAC7B,IAAIC,aAAoC;IAExC,IAAMC,QAAQ;QACZ,IAAID,YAAY;YACdE,aAAaF;YACbA,aAAa;QACf;QACA,IAAID,WAAWI,MAAM,GAAG,GAAG;YACzBX,GAAGO;YACHA,aAAa,EAAE;QACjB;IACF;IAEA,IAAMK,gBAAgB;QACpB,IAAI,CAACJ,YAAY;YACfA,aAAaK,WAAWJ,OAAOL;QACjC;IACF;IAEA,IAAMU,SAAS,IAAIC,gBAAQ,CAAC;QAC1BC,OAAAA,SAAAA,MAAMC,KAAK,EAAEC,IAAI,EAAEC,QAAQ;YACzB,IAAMC,OAAOd,OAAOW,MAAMI,QAAQ,CAAC;YACnC,IAAMC,QAAQF,KAAKG,KAAK,CAACxB;YACzBO,OAAOgB,MAAME,GAAG;YAEhB,IAAIF,MAAMX,MAAM,GAAG,GAAG;oBACpBJ;gBAAAA,CAAAA,cAAAA,YAAWkB,IAAI,OAAflB,aAAgB,qBAAGe;gBAEnB,8CAA8C;gBAC9C,IAAIf,WAAWI,MAAM,IAAIT,UAAU;oBACjCO;gBACF,OAAO;oBACLG;gBACF;YACF;YACAO;QACF;IACF;IAEAL,OAAOY,EAAE,CAAC,UAAU;QAClB,qCAAqC;QACrC,IAAIpB,KAAKK,MAAM,EAAEJ,WAAWkB,IAAI,CAACnB;QACjCG;QACAH,OAAO;IACT;IAEA,OAAOQ;AACT"}
|
|
@@ -8,16 +8,10 @@ Object.defineProperty(exports, "default", {
|
|
|
8
8
|
return concatWritable;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
var
|
|
12
|
-
function _interop_require_default(obj) {
|
|
13
|
-
return obj && obj.__esModule ? obj : {
|
|
14
|
-
default: obj
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
var Writable = _stream.default.Writable;
|
|
11
|
+
var _compatts = require("../compat.js");
|
|
18
12
|
function concatWritable(callback) {
|
|
19
13
|
var chunks = [];
|
|
20
|
-
var stream = new Writable({
|
|
14
|
+
var stream = new _compatts.Writable({
|
|
21
15
|
write: function(chunk, _encoding, next) {
|
|
22
16
|
chunks.push(chunk);
|
|
23
17
|
next();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/concatWritable.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/concatWritable.ts"],"sourcesContent":["import { Writable } from '../compat.ts';\n\nexport type Callback = (lines: Buffer) => void;\n\nexport default function concatWritable(callback: Callback): NodeJS.WritableStream {\n const chunks = [];\n const stream = new Writable({\n write: (chunk, _encoding, next) => {\n chunks.push(chunk);\n next();\n },\n });\n stream.on('finish', () => callback(Buffer.concat(chunks.splice(0))));\n return stream;\n}\n"],"names":["concatWritable","callback","chunks","stream","Writable","write","chunk","_encoding","next","push","on","Buffer","concat","splice"],"mappings":";;;;+BAIA;;;eAAwBA;;;wBAJC;AAIV,SAASA,eAAeC,QAAkB;IACvD,IAAMC,SAAS,EAAE;IACjB,IAAMC,SAAS,IAAIC,kBAAQ,CAAC;QAC1BC,OAAO,SAACC,OAAOC,WAAWC;YACxBN,OAAOO,IAAI,CAACH;YACZE;QACF;IACF;IACAL,OAAOO,EAAE,CAAC,UAAU;eAAMT,SAASU,OAAOC,MAAM,CAACV,OAAOW,MAAM,CAAC;;IAC/D,OAAOV;AACT"}
|
package/dist/cjs/lib/loadInk.js
CHANGED
|
@@ -63,13 +63,13 @@ function symlinkReactFromInk() {
|
|
|
63
63
|
// It's a real directory (e.g. from devDependencies) - leave it alone
|
|
64
64
|
return resolve();
|
|
65
65
|
}
|
|
66
|
-
} catch (
|
|
66
|
+
} catch (unused) {
|
|
67
67
|
// Doesn't exist, continue to create symlink
|
|
68
68
|
}
|
|
69
69
|
// Create symlink to ink's react
|
|
70
70
|
try {
|
|
71
71
|
_fs.default.symlinkSync(inkReactPath, reactPath);
|
|
72
|
-
} catch (
|
|
72
|
+
} catch (unused) {
|
|
73
73
|
// Ignore errors - react may have been installed another way
|
|
74
74
|
}
|
|
75
75
|
resolve();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/loadInk.ts"],"sourcesContent":["import fs from 'fs';\nimport installModule from 'install-module-linked';\nimport path from 'path';\nimport url from 'url';\n\n// Get the node_modules directory relative to this file\nconst _dirname = path.dirname(typeof __dirname !== 'undefined' ? __dirname : url.fileURLToPath(import.meta.url));\nconst nodeModules = path.join(_dirname, '..', '..', '..', 'node_modules');\n\nlet installed = false;\nlet installing: Promise<void> | null = null;\n\nfunction installDependency(name: string): Promise<void> {\n return new Promise((resolve, reject) => {\n // install-module-linked will:\n // 1. Check if module exists locally or in ~/.iml cache\n // 2. If not, install to ~/.iml\n // 3. Create symlink in nodeModules pointing to ~/.iml/package\n installModule(name, nodeModules, {}, (err) => {\n if (err) return reject(err);\n resolve();\n });\n });\n}\n\nfunction symlinkReactFromInk(): Promise<void> {\n return new Promise((resolve) => {\n // After ink is installed, symlink react to ink's react to avoid duplicate React instances\n const inkPath = fs.realpathSync(path.join(nodeModules, 'ink'));\n const inkReactPath = path.join(inkPath, 'node_modules', 'react');\n const reactPath = path.join(nodeModules, 'react');\n\n // Check if react already exists\n try {\n const stat = fs.lstatSync(reactPath);\n if (stat.isSymbolicLink()) {\n // It's a symlink - check if it points to the right place\n const existing = fs.readlinkSync(reactPath);\n if (existing === inkReactPath) {\n return resolve(); // Already correct\n }\n // Wrong symlink, remove it\n fs.unlinkSync(reactPath);\n } else {\n // It's a real directory (e.g. from devDependencies) - leave it alone\n return resolve();\n }\n } catch {\n // Doesn't exist, continue to create symlink\n }\n\n // Create symlink to ink's react\n try {\n fs.symlinkSync(inkReactPath, reactPath);\n } catch {\n // Ignore errors - react may have been installed another way\n }\n resolve();\n });\n}\n\nfunction installInk(): Promise<void> {\n if (installed) return Promise.resolve();\n if (installing) return installing;\n\n // Install ink, then symlink react to ink's bundled react\n // This ensures session.tsx and ink use the SAME React instance\n installing = installDependency('ink')\n .then(() => symlinkReactFromInk())\n .then(() => {\n installed = true;\n })\n .catch((err) => {\n installing = null;\n throw err;\n });\n\n return installing;\n}\n\nexport function loadInk(callback: (err: Error | null) => void): void {\n installInk()\n .then(() => callback(null))\n .catch((err) => callback(err));\n}\n\nexport function isInkInstalled(): boolean {\n return installed;\n}\n"],"names":["isInkInstalled","loadInk","_dirname","path","dirname","__dirname","url","fileURLToPath","nodeModules","join","installed","installing","installDependency","name","Promise","resolve","reject","installModule","err","symlinkReactFromInk","inkPath","fs","realpathSync","inkReactPath","reactPath","stat","lstatSync","isSymbolicLink","existing","readlinkSync","unlinkSync","symlinkSync","installInk","then","catch","callback"],"mappings":";;;;;;;;;;;QAsFgBA;eAAAA;;QANAC;eAAAA;;;yDAhFD;0EACW;2DACT;0DACD;;;;;;AAEhB,uDAAuD;AACvD,IAAMC,WAAWC,aAAI,CAACC,OAAO,CAAC,OAAOC,cAAc,cAAcA,YAAYC,YAAG,CAACC,aAAa,CAAC;AAC/F,IAAMC,cAAcL,aAAI,CAACM,IAAI,CAACP,UAAU,MAAM,MAAM,MAAM;AAE1D,IAAIQ,YAAY;AAChB,IAAIC,aAAmC;AAEvC,SAASC,kBAAkBC,IAAY;IACrC,OAAO,IAAIC,QAAQ,SAACC,SAASC;QAC3B,8BAA8B;QAC9B,uDAAuD;QACvD,+BAA+B;QAC/B,8DAA8D;QAC9DC,IAAAA,4BAAa,EAACJ,MAAML,aAAa,CAAC,GAAG,SAACU;YACpC,IAAIA,KAAK,OAAOF,OAAOE;YACvBH;QACF;IACF;AACF;AAEA,SAASI;IACP,OAAO,IAAIL,QAAQ,SAACC;QAClB,0FAA0F;QAC1F,IAAMK,UAAUC,WAAE,CAACC,YAAY,CAACnB,aAAI,CAACM,IAAI,CAACD,aAAa;QACvD,IAAMe,eAAepB,aAAI,CAACM,IAAI,CAACW,SAAS,gBAAgB;QACxD,IAAMI,YAAYrB,aAAI,CAACM,IAAI,CAACD,aAAa;QAEzC,gCAAgC;QAChC,IAAI;YACF,IAAMiB,OAAOJ,WAAE,CAACK,SAAS,CAACF;YAC1B,IAAIC,KAAKE,cAAc,IAAI;gBACzB,yDAAyD;gBACzD,IAAMC,WAAWP,WAAE,CAACQ,YAAY,CAACL;gBACjC,IAAII,aAAaL,cAAc;oBAC7B,OAAOR,WAAW,kBAAkB;gBACtC;gBACA,2BAA2B;gBAC3BM,WAAE,CAACS,UAAU,CAACN;YAChB,OAAO;gBACL,qEAAqE;gBACrE,OAAOT;YACT;QACF,EAAE,
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/loadInk.ts"],"sourcesContent":["import fs from 'fs';\nimport installModule from 'install-module-linked';\nimport path from 'path';\nimport url from 'url';\n\n// Get the node_modules directory relative to this file\nconst _dirname = path.dirname(typeof __dirname !== 'undefined' ? __dirname : url.fileURLToPath(import.meta.url));\nconst nodeModules = path.join(_dirname, '..', '..', '..', 'node_modules');\n\nlet installed = false;\nlet installing: Promise<void> | null = null;\n\nfunction installDependency(name: string): Promise<void> {\n return new Promise((resolve, reject) => {\n // install-module-linked will:\n // 1. Check if module exists locally or in ~/.iml cache\n // 2. If not, install to ~/.iml\n // 3. Create symlink in nodeModules pointing to ~/.iml/package\n installModule(name, nodeModules, {}, (err) => {\n if (err) return reject(err);\n resolve();\n });\n });\n}\n\nfunction symlinkReactFromInk(): Promise<void> {\n return new Promise((resolve) => {\n // After ink is installed, symlink react to ink's react to avoid duplicate React instances\n const inkPath = fs.realpathSync(path.join(nodeModules, 'ink'));\n const inkReactPath = path.join(inkPath, 'node_modules', 'react');\n const reactPath = path.join(nodeModules, 'react');\n\n // Check if react already exists\n try {\n const stat = fs.lstatSync(reactPath);\n if (stat.isSymbolicLink()) {\n // It's a symlink - check if it points to the right place\n const existing = fs.readlinkSync(reactPath);\n if (existing === inkReactPath) {\n return resolve(); // Already correct\n }\n // Wrong symlink, remove it\n fs.unlinkSync(reactPath);\n } else {\n // It's a real directory (e.g. from devDependencies) - leave it alone\n return resolve();\n }\n } catch {\n // Doesn't exist, continue to create symlink\n }\n\n // Create symlink to ink's react\n try {\n fs.symlinkSync(inkReactPath, reactPath);\n } catch {\n // Ignore errors - react may have been installed another way\n }\n resolve();\n });\n}\n\nfunction installInk(): Promise<void> {\n if (installed) return Promise.resolve();\n if (installing) return installing;\n\n // Install ink, then symlink react to ink's bundled react\n // This ensures session.tsx and ink use the SAME React instance\n installing = installDependency('ink')\n .then(() => symlinkReactFromInk())\n .then(() => {\n installed = true;\n })\n .catch((err) => {\n installing = null;\n throw err;\n });\n\n return installing;\n}\n\nexport function loadInk(callback: (err: Error | null) => void): void {\n installInk()\n .then(() => callback(null))\n .catch((err) => callback(err));\n}\n\nexport function isInkInstalled(): boolean {\n return installed;\n}\n"],"names":["isInkInstalled","loadInk","_dirname","path","dirname","__dirname","url","fileURLToPath","nodeModules","join","installed","installing","installDependency","name","Promise","resolve","reject","installModule","err","symlinkReactFromInk","inkPath","fs","realpathSync","inkReactPath","reactPath","stat","lstatSync","isSymbolicLink","existing","readlinkSync","unlinkSync","symlinkSync","installInk","then","catch","callback"],"mappings":";;;;;;;;;;;QAsFgBA;eAAAA;;QANAC;eAAAA;;;yDAhFD;0EACW;2DACT;0DACD;;;;;;AAEhB,uDAAuD;AACvD,IAAMC,WAAWC,aAAI,CAACC,OAAO,CAAC,OAAOC,cAAc,cAAcA,YAAYC,YAAG,CAACC,aAAa,CAAC;AAC/F,IAAMC,cAAcL,aAAI,CAACM,IAAI,CAACP,UAAU,MAAM,MAAM,MAAM;AAE1D,IAAIQ,YAAY;AAChB,IAAIC,aAAmC;AAEvC,SAASC,kBAAkBC,IAAY;IACrC,OAAO,IAAIC,QAAQ,SAACC,SAASC;QAC3B,8BAA8B;QAC9B,uDAAuD;QACvD,+BAA+B;QAC/B,8DAA8D;QAC9DC,IAAAA,4BAAa,EAACJ,MAAML,aAAa,CAAC,GAAG,SAACU;YACpC,IAAIA,KAAK,OAAOF,OAAOE;YACvBH;QACF;IACF;AACF;AAEA,SAASI;IACP,OAAO,IAAIL,QAAQ,SAACC;QAClB,0FAA0F;QAC1F,IAAMK,UAAUC,WAAE,CAACC,YAAY,CAACnB,aAAI,CAACM,IAAI,CAACD,aAAa;QACvD,IAAMe,eAAepB,aAAI,CAACM,IAAI,CAACW,SAAS,gBAAgB;QACxD,IAAMI,YAAYrB,aAAI,CAACM,IAAI,CAACD,aAAa;QAEzC,gCAAgC;QAChC,IAAI;YACF,IAAMiB,OAAOJ,WAAE,CAACK,SAAS,CAACF;YAC1B,IAAIC,KAAKE,cAAc,IAAI;gBACzB,yDAAyD;gBACzD,IAAMC,WAAWP,WAAE,CAACQ,YAAY,CAACL;gBACjC,IAAII,aAAaL,cAAc;oBAC7B,OAAOR,WAAW,kBAAkB;gBACtC;gBACA,2BAA2B;gBAC3BM,WAAE,CAACS,UAAU,CAACN;YAChB,OAAO;gBACL,qEAAqE;gBACrE,OAAOT;YACT;QACF,EAAE,eAAM;QACN,4CAA4C;QAC9C;QAEA,gCAAgC;QAChC,IAAI;YACFM,WAAE,CAACU,WAAW,CAACR,cAAcC;QAC/B,EAAE,eAAM;QACN,4DAA4D;QAC9D;QACAT;IACF;AACF;AAEA,SAASiB;IACP,IAAItB,WAAW,OAAOI,QAAQC,OAAO;IACrC,IAAIJ,YAAY,OAAOA;IAEvB,yDAAyD;IACzD,+DAA+D;IAC/DA,aAAaC,kBAAkB,OAC5BqB,IAAI,CAAC;eAAMd;OACXc,IAAI,CAAC;QACJvB,YAAY;IACd,GACCwB,KAAK,CAAC,SAAChB;QACNP,aAAa;QACb,MAAMO;IACR;IAEF,OAAOP;AACT;AAEO,SAASV,QAAQkC,QAAqC;IAC3DH,aACGC,IAAI,CAAC;eAAME,SAAS;OACpBD,KAAK,CAAC,SAAChB;eAAQiB,SAASjB;;AAC7B;AAEO,SAASlB;IACd,OAAOU;AACT"}
|
package/dist/cjs/session.js
CHANGED
|
@@ -125,12 +125,22 @@ function _object_spread_props(target, source) {
|
|
|
125
125
|
}
|
|
126
126
|
function _object_without_properties(source, excluded) {
|
|
127
127
|
if (source == null) return {};
|
|
128
|
-
var target =
|
|
129
|
-
|
|
128
|
+
var target = {}, sourceKeys, key, i;
|
|
129
|
+
if (typeof Reflect !== "undefined" && Reflect.ownKeys) {
|
|
130
|
+
sourceKeys = Reflect.ownKeys(source);
|
|
131
|
+
for(i = 0; i < sourceKeys.length; i++){
|
|
132
|
+
key = sourceKeys[i];
|
|
133
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
134
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
135
|
+
target[key] = source[key];
|
|
136
|
+
}
|
|
137
|
+
return target;
|
|
138
|
+
}
|
|
139
|
+
target = _object_without_properties_loose(source, excluded);
|
|
130
140
|
if (Object.getOwnPropertySymbols) {
|
|
131
|
-
|
|
132
|
-
for(i = 0; i <
|
|
133
|
-
key =
|
|
141
|
+
sourceKeys = Object.getOwnPropertySymbols(source);
|
|
142
|
+
for(i = 0; i < sourceKeys.length; i++){
|
|
143
|
+
key = sourceKeys[i];
|
|
134
144
|
if (excluded.indexOf(key) >= 0) continue;
|
|
135
145
|
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
136
146
|
target[key] = source[key];
|
|
@@ -140,12 +150,11 @@ function _object_without_properties(source, excluded) {
|
|
|
140
150
|
}
|
|
141
151
|
function _object_without_properties_loose(source, excluded) {
|
|
142
152
|
if (source == null) return {};
|
|
143
|
-
var target = {};
|
|
144
|
-
var sourceKeys = Object.keys(source);
|
|
145
|
-
var key, i;
|
|
153
|
+
var target = {}, sourceKeys = Object.getOwnPropertyNames(source), key, i;
|
|
146
154
|
for(i = 0; i < sourceKeys.length; i++){
|
|
147
155
|
key = sourceKeys[i];
|
|
148
156
|
if (excluded.indexOf(key) >= 0) continue;
|
|
157
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
149
158
|
target[key] = source[key];
|
|
150
159
|
}
|
|
151
160
|
return target;
|
|
@@ -155,6 +164,7 @@ var SessionImpl = /*#__PURE__*/ function() {
|
|
|
155
164
|
function SessionImpl() {
|
|
156
165
|
var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
157
166
|
_class_call_check(this, SessionImpl);
|
|
167
|
+
var _options_interactive;
|
|
158
168
|
this.inkApp = null;
|
|
159
169
|
this.runningCount = 0;
|
|
160
170
|
this.closed = false;
|
|
@@ -172,7 +182,6 @@ var SessionImpl = /*#__PURE__*/ function() {
|
|
|
172
182
|
maxFps: _constantsts.DEFAULT_MAX_FPS
|
|
173
183
|
});
|
|
174
184
|
}
|
|
175
|
-
var _options_interactive;
|
|
176
185
|
// Interactive mode requires a TTY to capture user input (e.g., press 'q' to quit)
|
|
177
186
|
// Force non-interactive when no UI is rendered, otherwise waitAndClose would hang
|
|
178
187
|
this.isInteractive = this.inkApp ? (_options_interactive = options.interactive) !== null && _options_interactive !== void 0 ? _options_interactive : false : false;
|
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 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 // 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 this.inkApp = render(<App store={this.store} />, {\n maxFps: DEFAULT_MAX_FPS,\n });\n }\n\n // Interactive mode requires a TTY to capture user input (e.g., press 'q' to quit)\n // Force non-interactive when no UI is rendered, otherwise waitAndClose would hang\n this.isInteractive = this.inkApp ? (options.interactive ?? false) : false;\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","terminalWidth","process","stdout","isTTY","render","App","maxFps","DEFAULT_MAX_FPS","isInteractive","interactive","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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"}
|
|
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 // 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 this.inkApp = render(<App store={this.store} />, {\n maxFps: DEFAULT_MAX_FPS,\n });\n }\n\n // Interactive mode requires a TTY to capture user input (e.g., press 'q' to quit)\n // Force non-interactive when no UI is rendered, otherwise waitAndClose would hang\n this.isInteractive = this.inkApp ? (options.interactive ?? false) : false;\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","terminalWidth","process","stdout","isTTY","render","App","maxFps","DEFAULT_MAX_FPS","isInteractive","interactive","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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"}
|
package/dist/cjs/src/compat.d.ts
CHANGED
|
@@ -2,5 +2,9 @@
|
|
|
2
2
|
* Compatibility Layer for Node.js 0.8+
|
|
3
3
|
* Local to this package - contains only needed functions.
|
|
4
4
|
*/
|
|
5
|
+
export declare const Readable: typeof import('stream').Readable;
|
|
6
|
+
export declare const Writable: typeof import('stream').Writable;
|
|
7
|
+
export declare const Transform: typeof import('stream').Transform;
|
|
8
|
+
export declare const PassThrough: typeof import('stream').PassThrough;
|
|
5
9
|
export declare function stringEndsWith(str: string, search: string, position?: number): boolean;
|
|
6
10
|
export declare function arrayFind<T>(arr: T[], predicate: (item: T, index: number, arr: T[]) => boolean): T | undefined;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type Callback = (lines: Buffer) =>
|
|
1
|
+
export type Callback = (lines: Buffer) => void;
|
|
2
2
|
export default function concatWritable(callback: Callback): NodeJS.WritableStream;
|
|
@@ -106,6 +106,7 @@ var ProcessStore = /*#__PURE__*/ function() {
|
|
|
106
106
|
var _this = this;
|
|
107
107
|
var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
108
108
|
_class_call_check(this, ProcessStore);
|
|
109
|
+
var _options_showStatusBar, _options_interactive;
|
|
109
110
|
// === DATA: Process collection ===
|
|
110
111
|
this.processes = [];
|
|
111
112
|
this.completedIds = []; // Track completion order
|
|
@@ -248,11 +249,11 @@ var ProcessStore = /*#__PURE__*/ function() {
|
|
|
248
249
|
};
|
|
249
250
|
// Get scroll offset for expanded process (or 0 if none)
|
|
250
251
|
this.getScrollOffset = function() {
|
|
252
|
+
var _ref;
|
|
251
253
|
var _process_scrollNav;
|
|
252
254
|
if (!_this.expandedId) return 0;
|
|
253
255
|
var process = _this.getProcess(_this.expandedId);
|
|
254
|
-
|
|
255
|
-
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;
|
|
256
|
+
return (_ref = process === null || process === void 0 ? void 0 : (_process_scrollNav = process.scrollNav) === null || _process_scrollNav === void 0 ? void 0 : _process_scrollNav.position) !== null && _ref !== void 0 ? _ref : 0;
|
|
256
257
|
};
|
|
257
258
|
// Session-level getters (set at session creation, immutable)
|
|
258
259
|
this.getHeader = function() {
|
|
@@ -276,9 +277,7 @@ var ProcessStore = /*#__PURE__*/ function() {
|
|
|
276
277
|
return _this.exitCallback;
|
|
277
278
|
};
|
|
278
279
|
this.header = options.header;
|
|
279
|
-
var _options_showStatusBar;
|
|
280
280
|
this.showStatusBar = (_options_showStatusBar = options.showStatusBar) !== null && _options_showStatusBar !== void 0 ? _options_showStatusBar : false;
|
|
281
|
-
var _options_interactive;
|
|
282
281
|
this.isInteractive = (_options_interactive = options.interactive) !== null && _options_interactive !== void 0 ? _options_interactive : false;
|
|
283
282
|
// Create list navigator with wrap-around behavior
|
|
284
283
|
// Uses filtered processes count so selection works correctly with filters
|
|
@@ -1 +1 @@
|
|
|
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';\ntype FilterMode = 'all' | 'running' | 'finished' | 'failed';\n\nconst FILTER_CYCLE: FilterMode[] = ['all', 'running', 'finished', 'failed'];\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 private filterMode: FilterMode = 'all';\n private searchTerm = '';\n private isSearching = false;\n private isFullscreen = false;\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 // Uses filtered processes count so selection works correctly with filters\n this.listNav = createNavigator({\n getLength: () => this.getFilteredProcesses().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 getFilterMode = (): FilterMode => this.filterMode;\n getSearchTerm = (): string => this.searchTerm;\n getIsSearching = (): boolean => this.isSearching;\n getIsFullscreen = (): boolean => this.isFullscreen;\n\n // Get processes filtered by current filter mode and search term\n getFilteredProcesses = (): ChildProcess[] => {\n let filtered = this.processes;\n\n // Apply filter mode\n switch (this.filterMode) {\n case 'running':\n filtered = filtered.filter((p) => p.state === 'running');\n break;\n case 'finished':\n filtered = filtered.filter((p) => p.state !== 'running');\n break;\n case 'failed':\n filtered = filtered.filter((p) => p.state === 'error');\n break;\n }\n\n // Apply search term\n if (this.searchTerm) {\n const term = this.searchTerm.toLowerCase();\n filtered = filtered.filter((p) => p.title.toLowerCase().includes(term) || (p.group && p.group.toLowerCase().includes(term)));\n }\n\n return filtered;\n };\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.getFilteredProcesses()[this.listNav.position];\n }\n\n // Filter mode cycling (left/right arrows)\n cycleFilterNext(): void {\n const currentIndex = FILTER_CYCLE.indexOf(this.filterMode);\n this.filterMode = FILTER_CYCLE[(currentIndex + 1) % FILTER_CYCLE.length] as FilterMode;\n // Reset selection when filter changes\n this.listNav.toStart();\n // Collapse any expanded process when filter changes\n this.expandedId = null;\n this.notify();\n }\n\n cycleFilterPrev(): void {\n const currentIndex = FILTER_CYCLE.indexOf(this.filterMode);\n this.filterMode = FILTER_CYCLE[(currentIndex - 1 + FILTER_CYCLE.length) % FILTER_CYCLE.length] as FilterMode;\n // Reset selection when filter changes\n this.listNav.toStart();\n // Collapse any expanded process when filter changes\n this.expandedId = null;\n this.notify();\n }\n\n // Search mode\n startSearch(): void {\n this.isSearching = true;\n this.searchTerm = '';\n this.notify();\n }\n\n updateSearchTerm(term: string): void {\n this.searchTerm = term;\n // Reset selection when search changes\n this.listNav.toStart();\n this.notify();\n }\n\n cancelSearch(): void {\n this.isSearching = false;\n this.searchTerm = '';\n // Reset selection\n this.listNav.toStart();\n this.notify();\n }\n\n confirmSearch(): void {\n this.isSearching = false;\n // Keep searchTerm applied, reset selection to first match\n this.listNav.toStart();\n this.notify();\n }\n\n clearSearch(): void {\n this.searchTerm = '';\n this.listNav.toStart();\n this.notify();\n }\n\n // Fullscreen mode (alternate screen buffer)\n enterFullscreen(): void {\n // If not expanded, expand the selected process first\n if (!this.expandedId) {\n const selected = this.getSelectedProcess();\n if (selected) {\n this.expandedId = selected.id;\n }\n }\n if (this.expandedId) {\n this.isFullscreen = true;\n this.notify();\n }\n }\n\n exitFullscreen(visibleCountWhenCollapsed?: number): void {\n this.isFullscreen = false;\n // Also collapse when exiting fullscreen\n this.expandedId = null;\n if (visibleCountWhenCollapsed) {\n this.listNav.clampViewport(visibleCountWhenCollapsed);\n }\n this.notify();\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.filterMode = 'all';\n this.searchTerm = '';\n this.isSearching = false;\n this.isFullscreen = 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","FILTER_CYCLE","options","processes","completedIds","mode","expandedId","errorFooterExpanded","filterMode","searchTerm","isSearching","isFullscreen","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","getFilterMode","getSearchTerm","getIsSearching","getIsFullscreen","getFilteredProcesses","filtered","term","toLowerCase","includes","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","appendLines","newLines","concat","terminalBuffer","getLines","text","type","LineType","stdout","lineCount","setMode","setPosition","getSelectedProcess","cycleFilterNext","currentIndex","indexOf","toStart","cycleFilterPrev","startSearch","updateSearchTerm","cancelSearch","confirmSearch","clearSearch","enterFullscreen","selected","exitFullscreen","visibleCountWhenCollapsed","clampViewport","toggleErrorFooter","expandErrorFooter","selectNext","visibleCount","down","ensureVisible","selectPrev","up","selectPageDown","pageSize","pageDown","selectPageUp","pageUp","selectFirst","selectLast","toEnd","clampListViewport","changed","getExpandedNav","nav","scrollDown","maxVisible","expanded","maxOffset","scrollUp","scrollPageDown","newPosition","min","scrollPageUp","scrollToTop","scrollToBottom","toggleExpand","visibleCountWhenExpanded","collapse","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';\ntype FilterMode = 'all' | 'running' | 'finished' | 'failed';\n\nconst FILTER_CYCLE: FilterMode[] = ['all', 'running', 'finished', 'failed'];\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 private filterMode: FilterMode = 'all';\n private searchTerm = '';\n private isSearching = false;\n private isFullscreen = false;\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 // Uses filtered processes count so selection works correctly with filters\n this.listNav = createNavigator({\n getLength: () => this.getFilteredProcesses().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 getFilterMode = (): FilterMode => this.filterMode;\n getSearchTerm = (): string => this.searchTerm;\n getIsSearching = (): boolean => this.isSearching;\n getIsFullscreen = (): boolean => this.isFullscreen;\n\n // Get processes filtered by current filter mode and search term\n getFilteredProcesses = (): ChildProcess[] => {\n let filtered = this.processes;\n\n // Apply filter mode\n switch (this.filterMode) {\n case 'running':\n filtered = filtered.filter((p) => p.state === 'running');\n break;\n case 'finished':\n filtered = filtered.filter((p) => p.state !== 'running');\n break;\n case 'failed':\n filtered = filtered.filter((p) => p.state === 'error');\n break;\n }\n\n // Apply search term\n if (this.searchTerm) {\n const term = this.searchTerm.toLowerCase();\n filtered = filtered.filter((p) => p.title.toLowerCase().includes(term) || (p.group && p.group.toLowerCase().includes(term)));\n }\n\n return filtered;\n };\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.getFilteredProcesses()[this.listNav.position];\n }\n\n // Filter mode cycling (left/right arrows)\n cycleFilterNext(): void {\n const currentIndex = FILTER_CYCLE.indexOf(this.filterMode);\n this.filterMode = FILTER_CYCLE[(currentIndex + 1) % FILTER_CYCLE.length] as FilterMode;\n // Reset selection when filter changes\n this.listNav.toStart();\n // Collapse any expanded process when filter changes\n this.expandedId = null;\n this.notify();\n }\n\n cycleFilterPrev(): void {\n const currentIndex = FILTER_CYCLE.indexOf(this.filterMode);\n this.filterMode = FILTER_CYCLE[(currentIndex - 1 + FILTER_CYCLE.length) % FILTER_CYCLE.length] as FilterMode;\n // Reset selection when filter changes\n this.listNav.toStart();\n // Collapse any expanded process when filter changes\n this.expandedId = null;\n this.notify();\n }\n\n // Search mode\n startSearch(): void {\n this.isSearching = true;\n this.searchTerm = '';\n this.notify();\n }\n\n updateSearchTerm(term: string): void {\n this.searchTerm = term;\n // Reset selection when search changes\n this.listNav.toStart();\n this.notify();\n }\n\n cancelSearch(): void {\n this.isSearching = false;\n this.searchTerm = '';\n // Reset selection\n this.listNav.toStart();\n this.notify();\n }\n\n confirmSearch(): void {\n this.isSearching = false;\n // Keep searchTerm applied, reset selection to first match\n this.listNav.toStart();\n this.notify();\n }\n\n clearSearch(): void {\n this.searchTerm = '';\n this.listNav.toStart();\n this.notify();\n }\n\n // Fullscreen mode (alternate screen buffer)\n enterFullscreen(): void {\n // If not expanded, expand the selected process first\n if (!this.expandedId) {\n const selected = this.getSelectedProcess();\n if (selected) {\n this.expandedId = selected.id;\n }\n }\n if (this.expandedId) {\n this.isFullscreen = true;\n this.notify();\n }\n }\n\n exitFullscreen(visibleCountWhenCollapsed?: number): void {\n this.isFullscreen = false;\n // Also collapse when exiting fullscreen\n this.expandedId = null;\n if (visibleCountWhenCollapsed) {\n this.listNav.clampViewport(visibleCountWhenCollapsed);\n }\n this.notify();\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.filterMode = 'all';\n this.searchTerm = '';\n this.isSearching = false;\n this.isFullscreen = 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","FILTER_CYCLE","options","processes","completedIds","mode","expandedId","errorFooterExpanded","filterMode","searchTerm","isSearching","isFullscreen","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","getFilterMode","getSearchTerm","getIsSearching","getIsFullscreen","getFilteredProcesses","filtered","term","toLowerCase","includes","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","appendLines","newLines","concat","terminalBuffer","getLines","text","type","LineType","stdout","lineCount","setMode","setPosition","getSelectedProcess","cycleFilterNext","currentIndex","indexOf","toStart","cycleFilterPrev","startSearch","updateSearchTerm","cancelSearch","confirmSearch","clearSearch","enterFullscreen","selected","exitFullscreen","visibleCountWhenCollapsed","clampViewport","toggleErrorFooter","expandErrorFooter","selectNext","visibleCount","down","ensureVisible","selectPrev","up","selectPageDown","pageSize","pageDown","selectPageUp","pageUp","selectFirst","selectLast","toEnd","clampListViewport","changed","getExpandedNav","nav","scrollDown","maxVisible","expanded","maxOffset","scrollUp","scrollPageDown","newPosition","min","scrollPageUp","scrollToTop","scrollToBottom","toggleExpand","visibleCountWhenExpanded","collapse","signalExit","callback","reset","dispose","forEach","l"],"mappings":";;;;+BAYaA;;;eAAAA;;;wBAZa;2BACW;uBAEZ;2BACuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMhD,IAAMC,eAA6B;IAAC;IAAO;IAAW;IAAY;CAAS;AAEpE,IAAA,AAAMD,6BAAN;;aAAMA;;YA4BCE,UAAAA,iEAA0B,CAAC;gCA5B5BF;YA8BYE,wBACAA;QA9BvB,mCAAmC;aAC3BC,YAA4B,EAAE;aAC9BC,eAAyB,EAAE,EAAE,yBAAyB;QAK9D,qBAAqB;aACbC,OAAa;aACbC,aAA4B;aAC5BC,sBAAsB,OAAO,mCAAmC;aAChEC,aAAyB;aACzBC,aAAa;aACbC,cAAc;aACdC,eAAe;aAIfC,gBAAgB;aAChBC,gBAAgB;QAExB,yBAAyB;aACjBC,YAAY,IAAIC;aAChBC,aAAa;aACbC,eAAoC;aACpCC,gBAAgB,GAAG,qDAAqD;QAgBhF,kDAAkD;aAElDC,YAAY,SAACC;YACX,MAAKN,SAAS,CAACO,GAAG,CAACD;YACnB,OAAO;uBAAM,MAAKN,SAAS,CAACQ,MAAM,CAACF;;QACrC;aAEAG,cAAc;mBAAsB,MAAKpB,SAAS;;QAElD,wBAAwB;aAExBqB,sBAAsB;YACpB,OAAO,MAAKrB,SAAS,CAACsB,MAAM,CAAC,SAACC;uBAAMA,EAAEC,KAAK,KAAK;;QAClD;aAEAC,wBAAwB;YACtB,6BAA6B;YAC7B,OAAO,MAAKxB,YAAY,CAACyB,GAAG,CAAC,SAACC;uBAAOC,IAAAA,mBAAS,EAAC,MAAK5B,SAAS,EAAE,SAACuB;2BAAMA,EAAEI,EAAE,KAAKA;;eAAKL,MAAM,CAAC,SAACC;uBAAyBA,MAAMM;;QAC7H;aAEAC,qBAAqB;YACnB,OAAO,MAAK9B,SAAS,CAACsB,MAAM,CAAC,SAACC;uBAAMA,EAAEC,KAAK,KAAK;;QAClD;QAEA,SAAS;aACTO,kBAAkB;mBAAc,MAAK/B,SAAS,CAACsB,MAAM,CAAC,SAACC;uBAAMA,EAAEC,KAAK,KAAK;eAAWQ,MAAM;;aAC1FC,oBAAoB;gBAEXC;YADP,IAAI,MAAKlC,SAAS,CAACgC,MAAM,KAAK,GAAG,OAAOG,iCAAoB;YAC5D,OAAOD,CAAAA,QAAAA,MAAKE,GAAG,OAARF,OAAS,qBAAG,MAAKlC,SAAS,CAAC0B,GAAG,CAAC,SAACH;uBAAM,AAACA,CAAAA,EAAEc,KAAK,IAAId,EAAEe,KAAK,AAAD,EAAGN,MAAM;;QAC1E;aACAO,eAAe;mBAAc,MAAKvC,SAAS,CAACsB,MAAM,CAAC,SAACC;uBAAMA,EAAEC,KAAK,KAAK;eAAWQ,MAAM;;aACvFQ,gBAAgB;mBAAc,MAAKxC,SAAS,CAACsB,MAAM,CAAC,SAACC;uBAAMA,EAAEC,KAAK,KAAK;eAASQ,MAAM;;aACtFS,oBAAoB;YAClB,OAAO,MAAKzC,SAAS,CAACsB,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,MAAK3C,IAAI;;aAC/B4C,mBAAmB;mBAAc,MAAKC,OAAO,CAACC,QAAQ;;aACtDC,gBAAgB;mBAAqB,MAAK9C,UAAU;;aACpD+C,sBAAsB;mBAAc,MAAKH,OAAO,CAACI,cAAc;;aAC/DC,yBAAyB;mBAAe,MAAKhD,mBAAmB;;aAChEiD,mBAAmB;mBAAc,MAAKtC,aAAa;;aACnDuC,gBAAgB;mBAAkB,MAAKjD,UAAU;;aACjDkD,gBAAgB;mBAAc,MAAKjD,UAAU;;aAC7CkD,iBAAiB;mBAAe,MAAKjD,WAAW;;aAChDkD,kBAAkB;mBAAe,MAAKjD,YAAY;;QAElD,gEAAgE;aAChEkD,uBAAuB;YACrB,IAAIC,WAAW,MAAK3D,SAAS;YAE7B,oBAAoB;YACpB,OAAQ,MAAKK,UAAU;gBACrB,KAAK;oBACHsD,WAAWA,SAASrC,MAAM,CAAC,SAACC;+BAAMA,EAAEC,KAAK,KAAK;;oBAC9C;gBACF,KAAK;oBACHmC,WAAWA,SAASrC,MAAM,CAAC,SAACC;+BAAMA,EAAEC,KAAK,KAAK;;oBAC9C;gBACF,KAAK;oBACHmC,WAAWA,SAASrC,MAAM,CAAC,SAACC;+BAAMA,EAAEC,KAAK,KAAK;;oBAC9C;YACJ;YAEA,oBAAoB;YACpB,IAAI,MAAKlB,UAAU,EAAE;gBACnB,IAAMsD,OAAO,MAAKtD,UAAU,CAACuD,WAAW;gBACxCF,WAAWA,SAASrC,MAAM,CAAC,SAACC;2BAAMA,EAAEe,KAAK,CAACuB,WAAW,GAAGC,QAAQ,CAACF,SAAUrC,EAAEc,KAAK,IAAId,EAAEc,KAAK,CAACwB,WAAW,GAAGC,QAAQ,CAACF;;YACvH;YAEA,OAAOD;QACT;QAEA,wDAAwD;aACxDI,kBAAkB;;gBAGTC;YAFP,IAAI,CAAC,MAAK7D,UAAU,EAAE,OAAO;YAC7B,IAAM6D,UAAU,MAAKC,UAAU,CAAC,MAAK9D,UAAU;YAC/C,eAAO6D,oBAAAA,+BAAAA,qBAAAA,QAASE,SAAS,cAAlBF,yCAAAA,mBAAoBhB,QAAQ,uCAAI;QACzC;QAEA,6DAA6D;aAC7DmB,YAAY;mBAA0B,MAAKC,MAAM;;aACjDC,mBAAmB;mBAAe,MAAK5D,aAAa;;aACpD6D,mBAAmB;mBAAe,MAAK5D,aAAa;;aACpD6D,gBAAgB;mBAAe,MAAKvE,SAAS,CAACgC,MAAM,GAAG,KAAK,MAAKhC,SAAS,CAACwE,KAAK,CAAC,SAACjD;uBAAMA,EAAEC,KAAK,KAAK;;;aA0QpGiD,gBAAgB;mBAAe,MAAK5D,UAAU;;aAC9C6D,kBAAkB;mBAA2B,MAAK5D,YAAY;;QA3b5D,IAAI,CAACsD,MAAM,GAAGrE,QAAQqE,MAAM;QAC5B,IAAI,CAAC3D,aAAa,IAAGV,yBAAAA,QAAQU,aAAa,cAArBV,oCAAAA,yBAAyB;QAC9C,IAAI,CAACW,aAAa,IAAGX,uBAAAA,QAAQ4E,WAAW,cAAnB5E,kCAAAA,uBAAuB;QAE5C,kDAAkD;QAClD,0EAA0E;QAC1E,IAAI,CAACgD,OAAO,GAAG6B,IAAAA,4BAAe,EAAC;YAC7BC,WAAW;uBAAM,MAAKnB,oBAAoB,GAAG1B,MAAM;;YACnD8C,MAAM;YACNC,QAAQ;uBAAM,MAAKC,MAAM;;QAC3B;;iBAvCSnF;IA8EXoF,OAAAA,aAKC,GALDA,SAAAA;;QACE,OAAO,IAAI,CAACnD,kBAAkB,GAAGJ,GAAG,CAAC,SAACH;mBAAO;gBAC3C2D,aAAa3D,EAAEc,KAAK,IAAId,EAAEe,KAAK;gBAC/B6C,OAAO,MAAKC,eAAe,CAAC7D,EAAEI,EAAE;YAClC;;IACF;IAEA,0BAA0B;IAE1B0D,OAAAA,UAYC,GAZDA,SAAAA,WAAWrB,OAAqB;;QAC9B,2CAA2C;QAC3C,IAAMsB,iBAA+B,wCAChCtB;YACHE,WAAWU,IAAAA,4BAAe,EAAC;gBACzBC,WAAW;2BAAM,MAAKjC,mBAAmB,CAAC0C,eAAe3D,EAAE;;gBAC3DmD,MAAM;gBACNC,QAAQ;2BAAM,MAAKC,MAAM;;YAC3B;;QAEF,IAAI,CAAChF,SAAS,GAAG,AAAC,qBAAG,IAAI,CAACA,SAAS,SAAlB;YAAoBsF;SAAe;QACpD,IAAI,CAACN,MAAM;IACb;IAEAO,OAAAA,aAkBC,GAlBDA,SAAAA,cAAc5D,EAAU,EAAE6D,MAA6B;QACrD,IAAMC,aAAa7D,IAAAA,mBAAS,EAAC,IAAI,CAAC5B,SAAS,EAAE,SAACuB;mBAAMA,EAAEI,EAAE,KAAKA;;QAC7D,IAAM+D,aAAaD,CAAAA,uBAAAA,iCAAAA,WAAYjE,KAAK,MAAK;QACzC,IAAMmE,gBAAgBH,OAAOhE,KAAK,IAAIgE,OAAOhE,KAAK,KAAK;QAEvD,IAAI,CAACxB,SAAS,GAAG,IAAI,CAACA,SAAS,CAAC0B,GAAG,CAAC,SAACH;mBAAOA,EAAEI,EAAE,KAAKA,KAAK,mBAAKJ,GAAMiE,UAAWjE;;QAEhF,yBAAyB;QACzB,IAAImE,cAAcC,iBAAiB,CAAC,IAAI,CAAC1F,YAAY,CAAC6D,QAAQ,CAACnC,KAAK;YAClE,IAAI,CAAC1B,YAAY,GAAG,AAAC,qBAAG,IAAI,CAACA,YAAY,SAArB;gBAAuB0B;aAAG;QAChD;QAEA,gFAAgF;QAChF,IAAI,CAAC,IAAI,CAACjB,aAAa,IAAI,IAAI,CAAC6D,aAAa,MAAM,IAAI,CAAC/B,aAAa,KAAK,GAAG;YAC3E,IAAI,CAACpC,mBAAmB,GAAG;QAC7B;QAEA,IAAI,CAAC4E,MAAM;IACb;IAEAY,OAAAA,WAKC,GALDA,SAAAA,YAAYjE,EAAU,EAAEkE,QAAgB;QACtC,IAAM7B,UAAUpC,IAAAA,mBAAS,EAAC,IAAI,CAAC5B,SAAS,EAAE,SAACuB;mBAAMA,EAAEI,EAAE,KAAKA;;QAC1D,IAAIqC,SAAS;YACX,IAAI,CAACuB,aAAa,CAAC5D,IAAI;gBAAEwD,OAAOnB,QAAQmB,KAAK,CAACW,MAAM,CAACD;YAAU;QACjE;IACF;IAEA5B,OAAAA,UAEC,GAFDA,SAAAA,WAAWtC,EAAU;QACnB,OAAOC,IAAAA,mBAAS,EAAC,IAAI,CAAC5B,SAAS,EAAE,SAACuB;mBAAMA,EAAEI,EAAE,KAAKA;;IACnD;IAEA,qEAAqE;IACrEyD,OAAAA,eAUC,GAVDA,SAAAA,gBAAgBzD,EAAU;QACxB,IAAMqC,UAAU,IAAI,CAACC,UAAU,CAACtC;QAChC,IAAI,CAACqC,SAAS,OAAO,EAAE;QACvB,IAAIA,QAAQ+B,cAAc,EAAE;YAC1B,OAAO/B,QAAQ+B,cAAc,CAACC,QAAQ,GAAGtE,GAAG,CAAC,SAACuE;uBAAU;oBACtDC,MAAMC,iBAAQ,CAACC,MAAM;oBACrBH,MAAAA;gBACF;;QACF;QACA,OAAOjC,QAAQmB,KAAK;IACtB;IAEA,qDAAqD;IACrDvC,OAAAA,mBAOC,GAPDA,SAAAA,oBAAoBjB,EAAU;QAC5B,IAAMqC,UAAU,IAAI,CAACC,UAAU,CAACtC;QAChC,IAAI,CAACqC,SAAS,OAAO;QACrB,IAAIA,QAAQ+B,cAAc,EAAE;YAC1B,OAAO/B,QAAQ+B,cAAc,CAACM,SAAS;QACzC;QACA,OAAOrC,QAAQmB,KAAK,CAACnD,MAAM;IAC7B;IAsDA,gCAAgC;IAEhCsE,OAAAA,OAMC,GANDA,SAAAA,QAAQpG,IAAU;QAChB,IAAI,CAACA,IAAI,GAAGA;QACZ,IAAIA,SAAS,eAAe;YAC1B,IAAI,CAAC6C,OAAO,CAACwD,WAAW,CAAC;QAC3B;QACA,IAAI,CAACvB,MAAM;IACb;IAEAwB,OAAAA,kBAEC,GAFDA,SAAAA;QACE,OAAO,IAAI,CAAC9C,oBAAoB,EAAE,CAAC,IAAI,CAACX,OAAO,CAACC,QAAQ,CAAC;IAC3D;IAEA,0CAA0C;IAC1CyD,OAAAA,eAQC,GARDA,SAAAA;QACE,IAAMC,eAAe5G,aAAa6G,OAAO,CAAC,IAAI,CAACtG,UAAU;QACzD,IAAI,CAACA,UAAU,GAAGP,YAAY,CAAC,AAAC4G,CAAAA,eAAe,CAAA,IAAK5G,aAAakC,MAAM,CAAC;QACxE,sCAAsC;QACtC,IAAI,CAACe,OAAO,CAAC6D,OAAO;QACpB,oDAAoD;QACpD,IAAI,CAACzG,UAAU,GAAG;QAClB,IAAI,CAAC6E,MAAM;IACb;IAEA6B,OAAAA,eAQC,GARDA,SAAAA;QACE,IAAMH,eAAe5G,aAAa6G,OAAO,CAAC,IAAI,CAACtG,UAAU;QACzD,IAAI,CAACA,UAAU,GAAGP,YAAY,CAAC,AAAC4G,CAAAA,eAAe,IAAI5G,aAAakC,MAAM,AAAD,IAAKlC,aAAakC,MAAM,CAAC;QAC9F,sCAAsC;QACtC,IAAI,CAACe,OAAO,CAAC6D,OAAO;QACpB,oDAAoD;QACpD,IAAI,CAACzG,UAAU,GAAG;QAClB,IAAI,CAAC6E,MAAM;IACb;IAEA,cAAc;IACd8B,OAAAA,WAIC,GAJDA,SAAAA;QACE,IAAI,CAACvG,WAAW,GAAG;QACnB,IAAI,CAACD,UAAU,GAAG;QAClB,IAAI,CAAC0E,MAAM;IACb;IAEA+B,OAAAA,gBAKC,GALDA,SAAAA,iBAAiBnD,IAAY;QAC3B,IAAI,CAACtD,UAAU,GAAGsD;QAClB,sCAAsC;QACtC,IAAI,CAACb,OAAO,CAAC6D,OAAO;QACpB,IAAI,CAAC5B,MAAM;IACb;IAEAgC,OAAAA,YAMC,GANDA,SAAAA;QACE,IAAI,CAACzG,WAAW,GAAG;QACnB,IAAI,CAACD,UAAU,GAAG;QAClB,kBAAkB;QAClB,IAAI,CAACyC,OAAO,CAAC6D,OAAO;QACpB,IAAI,CAAC5B,MAAM;IACb;IAEAiC,OAAAA,aAKC,GALDA,SAAAA;QACE,IAAI,CAAC1G,WAAW,GAAG;QACnB,0DAA0D;QAC1D,IAAI,CAACwC,OAAO,CAAC6D,OAAO;QACpB,IAAI,CAAC5B,MAAM;IACb;IAEAkC,OAAAA,WAIC,GAJDA,SAAAA;QACE,IAAI,CAAC5G,UAAU,GAAG;QAClB,IAAI,CAACyC,OAAO,CAAC6D,OAAO;QACpB,IAAI,CAAC5B,MAAM;IACb;IAEA,4CAA4C;IAC5CmC,OAAAA,eAYC,GAZDA,SAAAA;QACE,qDAAqD;QACrD,IAAI,CAAC,IAAI,CAAChH,UAAU,EAAE;YACpB,IAAMiH,WAAW,IAAI,CAACZ,kBAAkB;YACxC,IAAIY,UAAU;gBACZ,IAAI,CAACjH,UAAU,GAAGiH,SAASzF,EAAE;YAC/B;QACF;QACA,IAAI,IAAI,CAACxB,UAAU,EAAE;YACnB,IAAI,CAACK,YAAY,GAAG;YACpB,IAAI,CAACwE,MAAM;QACb;IACF;IAEAqC,OAAAA,cAQC,GARDA,SAAAA,eAAeC,yBAAkC;QAC/C,IAAI,CAAC9G,YAAY,GAAG;QACpB,wCAAwC;QACxC,IAAI,CAACL,UAAU,GAAG;QAClB,IAAImH,2BAA2B;YAC7B,IAAI,CAACvE,OAAO,CAACwE,aAAa,CAACD;QAC7B;QACA,IAAI,CAACtC,MAAM;IACb;IAEA,kDAAkD;IAClDwC,OAAAA,iBAGC,GAHDA,SAAAA;QACE,IAAI,CAACpH,mBAAmB,GAAG,CAAC,IAAI,CAACA,mBAAmB;QACpD,IAAI,CAAC4E,MAAM;IACb;IAEAyC,OAAAA,iBAKC,GALDA,SAAAA;QACE,IAAI,CAAC,IAAI,CAACrH,mBAAmB,EAAE;YAC7B,IAAI,CAACA,mBAAmB,GAAG;YAC3B,IAAI,CAAC4E,MAAM;QACb;IACF;IAEA,kDAAkD;IAElD0C,OAAAA,UAKC,GALDA,SAAAA,WAAWC,YAAqB;QAC9B,IAAI,CAAC5E,OAAO,CAAC6E,IAAI;QACjB,IAAID,cAAc;YAChB,IAAI,CAAC5E,OAAO,CAAC8E,aAAa,CAACF;QAC7B;IACF;IAEAG,OAAAA,UAKC,GALDA,SAAAA,WAAWH,YAAqB;QAC9B,IAAI,CAAC5E,OAAO,CAACgF,EAAE;QACf,IAAIJ,cAAc;YAChB,IAAI,CAAC5E,OAAO,CAAC8E,aAAa,CAACF;QAC7B;IACF;IAEAK,OAAAA,cAEC,GAFDA,SAAAA,eAAeC,QAAgB,EAAEN,YAAqB;QACpD,IAAI,CAAC5E,OAAO,CAACmF,QAAQ,CAACD,UAAUN;IAClC;IAEAQ,OAAAA,YAEC,GAFDA,SAAAA,aAAaF,QAAgB,EAAEN,YAAqB;QAClD,IAAI,CAAC5E,OAAO,CAACqF,MAAM,CAACH,UAAUN;IAChC;IAEAU,OAAAA,WAKC,GALDA,SAAAA,YAAYV,YAAqB;QAC/B,IAAI,CAAC5E,OAAO,CAAC6D,OAAO;QACpB,IAAIe,cAAc;YAChB,IAAI,CAAC5E,OAAO,CAAC8E,aAAa,CAACF;QAC7B;IACF;IAEAW,OAAAA,UAKC,GALDA,SAAAA,WAAWX,YAAqB;QAC9B,IAAI,CAAC5E,OAAO,CAACwF,KAAK;QAClB,IAAIZ,cAAc;YAChB,IAAI,CAAC5E,OAAO,CAAC8E,aAAa,CAACF;QAC7B;IACF;IAEAa,OAAAA,iBAKC,GALDA,SAAAA,kBAAkBb,YAAoB;QACpC,IAAMc,UAAU,IAAI,CAAC1F,OAAO,CAACwE,aAAa,CAACI;QAC3C,IAAIc,SAAS;YACX,IAAI,CAACzD,MAAM;QACb;IACF;IAEA,wEAAwE;IAExE,OAAQ0D,cAKP,GALD,SAAQA;YAEM;QADZ,IAAI,CAAC,IAAI,CAACvI,UAAU,EAAE,OAAO0B;QAC7B,IAAM8G,OAAM,mBAAA,IAAI,CAAC1E,UAAU,CAAC,IAAI,CAAC9D,UAAU,eAA/B,uCAAA,iBAAkC+D,SAAS;QACvD,IAAI,CAACyE,KAAK,OAAO9G;QACjB,OAAO;YAAE8G,KAAAA;YAAKhH,IAAI,IAAI,CAACxB,UAAU;QAAC;IACpC;IAEAyI,OAAAA,UAWC,GAXDA,SAAAA,WAAWC,UAAkB;QAC3B,IAAMC,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QAEf,IAAMzC,YAAY,IAAI,CAACzD,mBAAmB,CAACkG,SAASnH,EAAE;QACtD,IAAMoH,YAAY7G,KAAKE,GAAG,CAAC,GAAGiE,YAAYwC;QAE1C,+BAA+B;QAC/B,IAAIC,SAASH,GAAG,CAAC3F,QAAQ,GAAG+F,WAAW;YACrCD,SAASH,GAAG,CAACf,IAAI;QACnB;IACF;IAEAoB,OAAAA,QAOC,GAPDA,SAAAA;QACE,IAAMF,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QAEf,IAAIA,SAASH,GAAG,CAAC3F,QAAQ,GAAG,GAAG;YAC7B8F,SAASH,GAAG,CAACZ,EAAE;QACjB;IACF;IAEAkB,OAAAA,cAWC,GAXDA,SAAAA,eAAehB,QAAgB;QAC7B,IAAMa,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QAEf,IAAMzC,YAAY,IAAI,CAACzD,mBAAmB,CAACkG,SAASnH,EAAE;QACtD,IAAMoH,YAAY7G,KAAKE,GAAG,CAAC,GAAGiE,YAAY4B;QAE1C,sBAAsB;QACtB,IAAMiB,cAAchH,KAAKiH,GAAG,CAACL,SAASH,GAAG,CAAC3F,QAAQ,GAAGiF,UAAUc;QAC/DD,SAASH,GAAG,CAACpC,WAAW,CAAC2C;QACzB,IAAI,CAAClE,MAAM;IACb;IAEAoE,OAAAA,YAOC,GAPDA,SAAAA,aAAanB,QAAgB;QAC3B,IAAMa,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QAEf,IAAMI,cAAchH,KAAKE,GAAG,CAAC,GAAG0G,SAASH,GAAG,CAAC3F,QAAQ,GAAGiF;QACxDa,SAASH,GAAG,CAACpC,WAAW,CAAC2C;QACzB,IAAI,CAAClE,MAAM;IACb;IAEAqE,OAAAA,WAIC,GAJDA,SAAAA;QACE,IAAMP,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QACfA,SAASH,GAAG,CAAC/B,OAAO;IACtB;IAEA0C,OAAAA,cAQC,GARDA,SAAAA,eAAeT,UAAkB;QAC/B,IAAMC,WAAW,IAAI,CAACJ,cAAc;QACpC,IAAI,CAACI,UAAU;QAEf,IAAMzC,YAAY,IAAI,CAACzD,mBAAmB,CAACkG,SAASnH,EAAE;QACtD,IAAMuH,cAAchH,KAAKE,GAAG,CAAC,GAAGiE,YAAYwC;QAC5CC,SAASH,GAAG,CAACpC,WAAW,CAAC2C;QACzB,IAAI,CAAClE,MAAM;IACb;IAEA,oBAAoB;IAEpBuE,OAAAA,YAoBC,GApBDA,SAAAA,aAAaC,wBAAiC,EAAElC,yBAAkC;QAChF,IAAMF,WAAW,IAAI,CAACZ,kBAAkB;QACxC,IAAI,CAACY,UAAU;QAEf,IAAI,IAAI,CAACjH,UAAU,KAAKiH,SAASzF,EAAE,EAAE;YACnC,4CAA4C;YAC5C,IAAI,CAACxB,UAAU,GAAG;YAClB,iDAAiD;YACjD,IAAImH,2BAA2B;gBAC7B,IAAI,CAACvE,OAAO,CAACwE,aAAa,CAACD;YAC7B;QACF,OAAO;YACL,6DAA6D;YAC7D,IAAI,CAACnH,UAAU,GAAGiH,SAASzF,EAAE;YAC7B,sDAAsD;YACtD,IAAI6H,0BAA0B;gBAC5B,IAAI,CAACzG,OAAO,CAAC8E,aAAa,CAAC2B;YAC7B;QACF;QACA,IAAI,CAACxE,MAAM;IACb;IAEAyE,OAAAA,QAQC,GARDA,SAAAA,SAASnC,yBAAkC;QACzC,+CAA+C;QAC/C,IAAI,CAACnH,UAAU,GAAG;QAClB,iDAAiD;QACjD,IAAImH,2BAA2B;YAC7B,IAAI,CAACvE,OAAO,CAACwE,aAAa,CAACD;QAC7B;QACA,IAAI,CAACtC,MAAM;IACb;IAEA,eAAe;IAEf0E,OAAAA,UAIC,GAJDA,SAAAA,WAAWC,QAAoB;QAC7B,IAAI,CAAC9I,UAAU,GAAG;QAClB,IAAI,CAACC,YAAY,GAAG6I;QACpB,IAAI,CAAC3E,MAAM;IACb;IAKA,gBAAgB;IAEhB4E,OAAAA,KAkBC,GAlBDA,SAAAA;YAEO,kCAAA,2BAAA;;YADL,2CAA2C;YAC3C,QAAK,YAAiB,IAAI,CAAC5J,SAAS,qBAA/B,SAAA,6BAAA,QAAA,yBAAA,iCAAiC;gBAAjC,IAAMgE,UAAN;oBACHA;iBAAAA,0BAAAA,QAAQ+B,cAAc,cAAtB/B,8CAAAA,wBAAwB6F,OAAO;YACjC;;YAFK;YAAA;;;qBAAA,6BAAA;oBAAA;;;oBAAA;0BAAA;;;;QAGL,IAAI,CAAC7J,SAAS,GAAG,EAAE;QACnB,IAAI,CAACC,YAAY,GAAG,EAAE;QACtB,IAAI,CAACY,UAAU,GAAG;QAClB,IAAI,CAACC,YAAY,GAAG;QACpB,IAAI,CAACZ,IAAI,GAAG;QACZ,IAAI,CAAC6C,OAAO,CAAC6G,KAAK;QAClB,IAAI,CAACzJ,UAAU,GAAG;QAClB,IAAI,CAACC,mBAAmB,GAAG;QAC3B,IAAI,CAACC,UAAU,GAAG;QAClB,IAAI,CAACC,UAAU,GAAG;QAClB,IAAI,CAACC,WAAW,GAAG;QACnB,IAAI,CAACC,YAAY,GAAG;QACpB,IAAI,CAAC4D,MAAM,GAAGvC;IAChB;IAEA,yBAAyB;IAEzBmD,OAAAA,MAKC,GALDA,SAAAA;QACE,IAAI,CAACjE,aAAa;QAClB,IAAI,CAACJ,SAAS,CAACmJ,OAAO,CAAC,SAACC;YACtBA;QACF;IACF;WAvfWlK;EA0fb,qEAAqE"}
|
package/dist/esm/compat.js
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Compatibility Layer for Node.js 0.8+
|
|
3
3
|
* Local to this package - contains only needed functions.
|
|
4
|
-
*/
|
|
4
|
+
*/ import Module from 'module';
|
|
5
|
+
const _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;
|
|
6
|
+
/**
|
|
7
|
+
* Stream compatibility - Transform class
|
|
8
|
+
* - Uses native stream.Transform on Node 0.10+
|
|
9
|
+
* - Falls back to readable-stream for Node 0.8
|
|
10
|
+
*/ const major = +process.versions.node.split('.')[0];
|
|
11
|
+
export const Readable = major > 0 ? _require('stream').Readable : _require('readable-stream').Readable;
|
|
12
|
+
export const Writable = major > 0 ? _require('stream').Writable : _require('readable-stream').Writable;
|
|
13
|
+
export const Transform = major > 0 ? _require('stream').Transform : _require('readable-stream').Transform;
|
|
14
|
+
export const PassThrough = major > 0 ? _require('stream').PassThrough : _require('readable-stream').PassThrough;
|
|
15
|
+
/**
|
|
5
16
|
* String.prototype.endsWith wrapper for Node.js 0.8+
|
|
6
17
|
* - Uses native endsWith on Node 4.0+ / ES2015+
|
|
7
18
|
* - Falls back to lastIndexOf on Node 0.8-3.x
|
package/dist/esm/compat.js.map
CHANGED
|
@@ -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 */\nconst hasEndsWith = typeof String.prototype.endsWith === 'function';\
|
|
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\nimport Module from 'module';\n\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\n\n/**\n * Stream compatibility - Transform class\n * - Uses native stream.Transform on Node 0.10+\n * - Falls back to readable-stream for Node 0.8\n */\nconst major = +process.versions.node.split('.')[0];\nexport const Readable: typeof import('stream').Readable = major > 0 ? _require('stream').Readable : _require('readable-stream').Readable;\nexport const Writable: typeof import('stream').Writable = major > 0 ? _require('stream').Writable : _require('readable-stream').Writable;\nexport const Transform: typeof import('stream').Transform = major > 0 ? _require('stream').Transform : _require('readable-stream').Transform;\nexport const PassThrough: typeof import('stream').PassThrough = major > 0 ? _require('stream').PassThrough : _require('readable-stream').PassThrough;\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 */\nconst hasEndsWith = typeof String.prototype.endsWith === 'function';\nexport function stringEndsWith(str: string, search: string, position?: number): boolean {\n if (hasEndsWith) {\n return str.endsWith(search, position);\n }\n const 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 */\nconst 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 (let i = 0; i < arr.length; i++) {\n if (predicate(arr[i], i, arr)) return arr[i];\n }\n return undefined;\n}\n"],"names":["Module","_require","require","createRequire","url","major","process","versions","node","split","Readable","Writable","Transform","PassThrough","hasEndsWith","String","prototype","endsWith","stringEndsWith","str","search","position","len","undefined","length","lastIndexOf","hasArrayFind","Array","find","arrayFind","arr","predicate","i"],"mappings":"AAAA;;;CAGC,GAED,OAAOA,YAAY,SAAS;AAE5B,MAAMC,WAAW,OAAOC,YAAY,cAAcF,OAAOG,aAAa,CAAC,YAAYC,GAAG,IAAIF;AAE1F;;;;CAIC,GACD,MAAMG,QAAQ,CAACC,QAAQC,QAAQ,CAACC,IAAI,CAACC,KAAK,CAAC,IAAI,CAAC,EAAE;AAClD,OAAO,MAAMC,WAA6CL,QAAQ,IAAIJ,SAAS,UAAUS,QAAQ,GAAGT,SAAS,mBAAmBS,QAAQ,CAAC;AACzI,OAAO,MAAMC,WAA6CN,QAAQ,IAAIJ,SAAS,UAAUU,QAAQ,GAAGV,SAAS,mBAAmBU,QAAQ,CAAC;AACzI,OAAO,MAAMC,YAA+CP,QAAQ,IAAIJ,SAAS,UAAUW,SAAS,GAAGX,SAAS,mBAAmBW,SAAS,CAAC;AAC7I,OAAO,MAAMC,cAAmDR,QAAQ,IAAIJ,SAAS,UAAUY,WAAW,GAAGZ,SAAS,mBAAmBY,WAAW,CAAC;AAErJ;;;;CAIC,GACD,MAAMC,cAAc,OAAOC,OAAOC,SAAS,CAACC,QAAQ,KAAK;AACzD,OAAO,SAASC,eAAeC,GAAW,EAAEC,MAAc,EAAEC,QAAiB;IAC3E,IAAIP,aAAa;QACf,OAAOK,IAAIF,QAAQ,CAACG,QAAQC;IAC9B;IACA,MAAMC,MAAMD,aAAaE,YAAYJ,IAAIK,MAAM,GAAGH;IAClD,OAAOF,IAAIM,WAAW,CAACL,YAAYE,MAAMF,OAAOI,MAAM;AACxD;AAEA;;;;CAIC,GACD,MAAME,eAAe,OAAOC,MAAMX,SAAS,CAACY,IAAI,KAAK;AAErD,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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/addLines.ts"],"sourcesContent":["import { Writable } from 'stream';\nimport { BATCH_MAX_LINES, BATCH_MAX_WAIT_MS } from '../constants.ts';\n\nconst REGEX_NEW_LINE = /\\r?\\n|\\r/g;\n\nexport type Callback = (lines: string[]) =>
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/addLines.ts"],"sourcesContent":["import { Writable } from 'stream';\nimport { BATCH_MAX_LINES, BATCH_MAX_WAIT_MS } from '../constants.ts';\n\nconst REGEX_NEW_LINE = /\\r?\\n|\\r/g;\n\nexport type Callback = (lines: string[]) => void;\n\ninterface BatchOptions {\n maxLines?: number;\n maxWait?: number;\n}\n\nexport default function addLines(fn: Callback, options: BatchOptions = {}): Writable {\n const { maxLines = BATCH_MAX_LINES, maxWait = BATCH_MAX_WAIT_MS } = options;\n\n let last = '';\n let lineBuffer: string[] = [];\n let flushTimer: NodeJS.Timeout | null = null;\n\n const flush = () => {\n if (flushTimer) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n if (lineBuffer.length > 0) {\n fn(lineBuffer);\n lineBuffer = [];\n }\n };\n\n const scheduleFlush = () => {\n if (!flushTimer) {\n flushTimer = setTimeout(flush, maxWait);\n }\n };\n\n const stream = new Writable({\n write(chunk, _enc, callback) {\n const more = last + chunk.toString('utf8');\n const lines = more.split(REGEX_NEW_LINE);\n last = lines.pop();\n\n if (lines.length > 0) {\n lineBuffer.push(...lines);\n\n // Flush immediately if buffer is large enough\n if (lineBuffer.length >= maxLines) {\n flush();\n } else {\n scheduleFlush();\n }\n }\n callback();\n },\n });\n\n stream.on('finish', () => {\n // Flush any remaining buffered lines\n if (last.length) lineBuffer.push(last);\n flush();\n last = '';\n });\n\n return stream;\n}\n"],"names":["Writable","BATCH_MAX_LINES","BATCH_MAX_WAIT_MS","REGEX_NEW_LINE","addLines","fn","options","maxLines","maxWait","last","lineBuffer","flushTimer","flush","clearTimeout","length","scheduleFlush","setTimeout","stream","write","chunk","_enc","callback","more","toString","lines","split","pop","push","on"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,SAAS;AAClC,SAASC,eAAe,EAAEC,iBAAiB,QAAQ,kBAAkB;AAErE,MAAMC,iBAAiB;AASvB,eAAe,SAASC,SAASC,EAAY,EAAEC,UAAwB,CAAC,CAAC;IACvE,MAAM,EAAEC,WAAWN,eAAe,EAAEO,UAAUN,iBAAiB,EAAE,GAAGI;IAEpE,IAAIG,OAAO;IACX,IAAIC,aAAuB,EAAE;IAC7B,IAAIC,aAAoC;IAExC,MAAMC,QAAQ;QACZ,IAAID,YAAY;YACdE,aAAaF;YACbA,aAAa;QACf;QACA,IAAID,WAAWI,MAAM,GAAG,GAAG;YACzBT,GAAGK;YACHA,aAAa,EAAE;QACjB;IACF;IAEA,MAAMK,gBAAgB;QACpB,IAAI,CAACJ,YAAY;YACfA,aAAaK,WAAWJ,OAAOJ;QACjC;IACF;IAEA,MAAMS,SAAS,IAAIjB,SAAS;QAC1BkB,OAAMC,KAAK,EAAEC,IAAI,EAAEC,QAAQ;YACzB,MAAMC,OAAOb,OAAOU,MAAMI,QAAQ,CAAC;YACnC,MAAMC,QAAQF,KAAKG,KAAK,CAACtB;YACzBM,OAAOe,MAAME,GAAG;YAEhB,IAAIF,MAAMV,MAAM,GAAG,GAAG;gBACpBJ,WAAWiB,IAAI,IAAIH;gBAEnB,8CAA8C;gBAC9C,IAAId,WAAWI,MAAM,IAAIP,UAAU;oBACjCK;gBACF,OAAO;oBACLG;gBACF;YACF;YACAM;QACF;IACF;IAEAJ,OAAOW,EAAE,CAAC,UAAU;QAClB,qCAAqC;QACrC,IAAInB,KAAKK,MAAM,EAAEJ,WAAWiB,IAAI,CAAClB;QACjCG;QACAH,OAAO;IACT;IAEA,OAAOQ;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/concatWritable.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/node/spawn-term/src/lib/concatWritable.ts"],"sourcesContent":["import { Writable } from '../compat.ts';\n\nexport type Callback = (lines: Buffer) => void;\n\nexport default function concatWritable(callback: Callback): NodeJS.WritableStream {\n const chunks = [];\n const stream = new Writable({\n write: (chunk, _encoding, next) => {\n chunks.push(chunk);\n next();\n },\n });\n stream.on('finish', () => callback(Buffer.concat(chunks.splice(0))));\n return stream;\n}\n"],"names":["Writable","concatWritable","callback","chunks","stream","write","chunk","_encoding","next","push","on","Buffer","concat","splice"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,eAAe;AAIxC,eAAe,SAASC,eAAeC,QAAkB;IACvD,MAAMC,SAAS,EAAE;IACjB,MAAMC,SAAS,IAAIJ,SAAS;QAC1BK,OAAO,CAACC,OAAOC,WAAWC;YACxBL,OAAOM,IAAI,CAACH;YACZE;QACF;IACF;IACAJ,OAAOM,EAAE,CAAC,UAAU,IAAMR,SAASS,OAAOC,MAAM,CAACT,OAAOU,MAAM,CAAC;IAC/D,OAAOT;AACT"}
|
package/dist/esm/session.js
CHANGED
|
@@ -215,6 +215,7 @@ let SessionImpl = class SessionImpl {
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
constructor(options = {}){
|
|
218
|
+
var _options_interactive;
|
|
218
219
|
this.inkApp = null;
|
|
219
220
|
this.runningCount = 0;
|
|
220
221
|
this.closed = false;
|
|
@@ -232,7 +233,6 @@ let SessionImpl = class SessionImpl {
|
|
|
232
233
|
maxFps: DEFAULT_MAX_FPS
|
|
233
234
|
});
|
|
234
235
|
}
|
|
235
|
-
var _options_interactive;
|
|
236
236
|
// Interactive mode requires a TTY to capture user input (e.g., press 'q' to quit)
|
|
237
237
|
// Force non-interactive when no UI is rendered, otherwise waitAndClose would hang
|
|
238
238
|
this.isInteractive = this.inkApp ? (_options_interactive = options.interactive) !== null && _options_interactive !== void 0 ? _options_interactive : false : false;
|
package/dist/esm/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 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 // 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 this.inkApp = render(<App store={this.store} />, {\n maxFps: DEFAULT_MAX_FPS,\n });\n }\n\n // Interactive mode requires a TTY to capture user input (e.g., press 'q' to quit)\n // Force non-interactive when no UI is rendered, otherwise waitAndClose would hang\n this.isInteractive = this.inkApp ? (options.interactive ?? false) : false;\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":["spawn","crossSpawn","crypto","render","oo","Queue","App","DEFAULT_MAX_FPS","concatWritable","formatArguments","TerminalBuffer","ProcessStore","SessionImpl","command","args","spawnOptions","options","callback","closed","Error","encoding","stdio","csOptions","inkApp","cp","worker","err","res","stdout","stderr","output","runningCount","id","randomUUID","terminalBuffer","terminalWidth","store","addProcess","title","concat","join","state","lines","group","expanded","on","chunk","write","notify","queue","defer","bind","await","updateProcess","onProcessComplete","outputs","toString","pipe","close","cleanup","waitAndClose","waitCallbacks","push","isInteractive","unsubscribe","subscribe","getShouldExit","closeAndCallWaitCallbacks","length","cb","onComplete","signalExit","reset","process","waitUntilExit","then","getExitCallback","catch","isTTY","maxFps","interactive","createSession"],"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 // 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 this.inkApp = render(<App store={this.store} />, {\n maxFps: DEFAULT_MAX_FPS,\n });\n }\n\n // Interactive mode requires a TTY to capture user input (e.g., press 'q' to quit)\n // Force non-interactive when no UI is rendered, otherwise waitAndClose would hang\n this.isInteractive = this.inkApp ? (options.interactive ?? false) : false;\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":["spawn","crossSpawn","crypto","render","oo","Queue","App","DEFAULT_MAX_FPS","concatWritable","formatArguments","TerminalBuffer","ProcessStore","SessionImpl","command","args","spawnOptions","options","callback","closed","Error","encoding","stdio","csOptions","inkApp","cp","worker","err","res","stdout","stderr","output","runningCount","id","randomUUID","terminalBuffer","terminalWidth","store","addProcess","title","concat","join","state","lines","group","expanded","on","chunk","write","notify","queue","defer","bind","await","updateProcess","onProcessComplete","outputs","toString","pipe","close","cleanup","waitAndClose","waitCallbacks","push","isInteractive","unsubscribe","subscribe","getShouldExit","closeAndCallWaitCallbacks","length","cb","onComplete","signalExit","reset","process","waitUntilExit","then","getExitCallback","catch","isTTY","maxFps","interactive","createSession"],"mappings":"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"}
|
package/dist/esm/src/compat.d.ts
CHANGED
|
@@ -2,5 +2,9 @@
|
|
|
2
2
|
* Compatibility Layer for Node.js 0.8+
|
|
3
3
|
* Local to this package - contains only needed functions.
|
|
4
4
|
*/
|
|
5
|
+
export declare const Readable: typeof import('stream').Readable;
|
|
6
|
+
export declare const Writable: typeof import('stream').Writable;
|
|
7
|
+
export declare const Transform: typeof import('stream').Transform;
|
|
8
|
+
export declare const PassThrough: typeof import('stream').PassThrough;
|
|
5
9
|
export declare function stringEndsWith(str: string, search: string, position?: number): boolean;
|
|
6
10
|
export declare function arrayFind<T>(arr: T[], predicate: (item: T, index: number, arr: T[]) => boolean): T | undefined;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type Callback = (lines: Buffer) =>
|
|
1
|
+
export type Callback = (lines: Buffer) => void;
|
|
2
2
|
export default function concatWritable(callback: Callback): NodeJS.WritableStream;
|
|
@@ -339,6 +339,7 @@ export class ProcessStore {
|
|
|
339
339
|
});
|
|
340
340
|
}
|
|
341
341
|
constructor(options = {}){
|
|
342
|
+
var _options_showStatusBar, _options_interactive;
|
|
342
343
|
// === DATA: Process collection ===
|
|
343
344
|
this.processes = [];
|
|
344
345
|
this.completedIds = []; // Track completion order
|
|
@@ -420,11 +421,11 @@ export class ProcessStore {
|
|
|
420
421
|
};
|
|
421
422
|
// Get scroll offset for expanded process (or 0 if none)
|
|
422
423
|
this.getScrollOffset = ()=>{
|
|
424
|
+
var _ref;
|
|
423
425
|
var _process_scrollNav;
|
|
424
426
|
if (!this.expandedId) return 0;
|
|
425
427
|
const process = this.getProcess(this.expandedId);
|
|
426
|
-
|
|
427
|
-
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;
|
|
428
|
+
return (_ref = process === null || process === void 0 ? void 0 : (_process_scrollNav = process.scrollNav) === null || _process_scrollNav === void 0 ? void 0 : _process_scrollNav.position) !== null && _ref !== void 0 ? _ref : 0;
|
|
428
429
|
};
|
|
429
430
|
// Session-level getters (set at session creation, immutable)
|
|
430
431
|
this.getHeader = ()=>this.header;
|
|
@@ -434,9 +435,7 @@ export class ProcessStore {
|
|
|
434
435
|
this.getShouldExit = ()=>this.shouldExit;
|
|
435
436
|
this.getExitCallback = ()=>this.exitCallback;
|
|
436
437
|
this.header = options.header;
|
|
437
|
-
var _options_showStatusBar;
|
|
438
438
|
this.showStatusBar = (_options_showStatusBar = options.showStatusBar) !== null && _options_showStatusBar !== void 0 ? _options_showStatusBar : false;
|
|
439
|
-
var _options_interactive;
|
|
440
439
|
this.isInteractive = (_options_interactive = options.interactive) !== null && _options_interactive !== void 0 ? _options_interactive : false;
|
|
441
440
|
// Create list navigator with wrap-around behavior
|
|
442
441
|
// Uses filtered processes count so selection works correctly with filters
|
|
@@ -1 +1 @@
|
|
|
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';\ntype FilterMode = 'all' | 'running' | 'finished' | 'failed';\n\nconst FILTER_CYCLE: FilterMode[] = ['all', 'running', 'finished', 'failed'];\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 private filterMode: FilterMode = 'all';\n private searchTerm = '';\n private isSearching = false;\n private isFullscreen = false;\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 // Uses filtered processes count so selection works correctly with filters\n this.listNav = createNavigator({\n getLength: () => this.getFilteredProcesses().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 getFilterMode = (): FilterMode => this.filterMode;\n getSearchTerm = (): string => this.searchTerm;\n getIsSearching = (): boolean => this.isSearching;\n getIsFullscreen = (): boolean => this.isFullscreen;\n\n // Get processes filtered by current filter mode and search term\n getFilteredProcesses = (): ChildProcess[] => {\n let filtered = this.processes;\n\n // Apply filter mode\n switch (this.filterMode) {\n case 'running':\n filtered = filtered.filter((p) => p.state === 'running');\n break;\n case 'finished':\n filtered = filtered.filter((p) => p.state !== 'running');\n break;\n case 'failed':\n filtered = filtered.filter((p) => p.state === 'error');\n break;\n }\n\n // Apply search term\n if (this.searchTerm) {\n const term = this.searchTerm.toLowerCase();\n filtered = filtered.filter((p) => p.title.toLowerCase().includes(term) || (p.group && p.group.toLowerCase().includes(term)));\n }\n\n return filtered;\n };\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.getFilteredProcesses()[this.listNav.position];\n }\n\n // Filter mode cycling (left/right arrows)\n cycleFilterNext(): void {\n const currentIndex = FILTER_CYCLE.indexOf(this.filterMode);\n this.filterMode = FILTER_CYCLE[(currentIndex + 1) % FILTER_CYCLE.length] as FilterMode;\n // Reset selection when filter changes\n this.listNav.toStart();\n // Collapse any expanded process when filter changes\n this.expandedId = null;\n this.notify();\n }\n\n cycleFilterPrev(): void {\n const currentIndex = FILTER_CYCLE.indexOf(this.filterMode);\n this.filterMode = FILTER_CYCLE[(currentIndex - 1 + FILTER_CYCLE.length) % FILTER_CYCLE.length] as FilterMode;\n // Reset selection when filter changes\n this.listNav.toStart();\n // Collapse any expanded process when filter changes\n this.expandedId = null;\n this.notify();\n }\n\n // Search mode\n startSearch(): void {\n this.isSearching = true;\n this.searchTerm = '';\n this.notify();\n }\n\n updateSearchTerm(term: string): void {\n this.searchTerm = term;\n // Reset selection when search changes\n this.listNav.toStart();\n this.notify();\n }\n\n cancelSearch(): void {\n this.isSearching = false;\n this.searchTerm = '';\n // Reset selection\n this.listNav.toStart();\n this.notify();\n }\n\n confirmSearch(): void {\n this.isSearching = false;\n // Keep searchTerm applied, reset selection to first match\n this.listNav.toStart();\n this.notify();\n }\n\n clearSearch(): void {\n this.searchTerm = '';\n this.listNav.toStart();\n this.notify();\n }\n\n // Fullscreen mode (alternate screen buffer)\n enterFullscreen(): void {\n // If not expanded, expand the selected process first\n if (!this.expandedId) {\n const selected = this.getSelectedProcess();\n if (selected) {\n this.expandedId = selected.id;\n }\n }\n if (this.expandedId) {\n this.isFullscreen = true;\n this.notify();\n }\n }\n\n exitFullscreen(visibleCountWhenCollapsed?: number): void {\n this.isFullscreen = false;\n // Also collapse when exiting fullscreen\n this.expandedId = null;\n if (visibleCountWhenCollapsed) {\n this.listNav.clampViewport(visibleCountWhenCollapsed);\n }\n this.notify();\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.filterMode = 'all';\n this.searchTerm = '';\n this.isSearching = false;\n this.isFullscreen = 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":["arrayFind","DEFAULT_COLUMN_WIDTH","LineType","createNavigator","FILTER_CYCLE","ProcessStore","getErrorLines","getFailedProcesses","map","p","processName","group","title","lines","getProcessLines","id","addProcess","process","processWithNav","scrollNav","getLength","getProcessLineCount","wrap","onMove","notify","processes","updateProcess","update","oldProcess","wasRunning","state","isNowComplete","completedIds","includes","isInteractive","isAllComplete","getErrorCount","errorFooterExpanded","appendLines","newLines","concat","getProcess","terminalBuffer","getLines","text","type","stdout","lineCount","length","setMode","mode","listNav","setPosition","getSelectedProcess","getFilteredProcesses","position","cycleFilterNext","currentIndex","indexOf","filterMode","toStart","expandedId","cycleFilterPrev","startSearch","isSearching","searchTerm","updateSearchTerm","term","cancelSearch","confirmSearch","clearSearch","enterFullscreen","selected","isFullscreen","exitFullscreen","visibleCountWhenCollapsed","clampViewport","toggleErrorFooter","expandErrorFooter","selectNext","visibleCount","down","ensureVisible","selectPrev","up","selectPageDown","pageSize","pageDown","selectPageUp","pageUp","selectFirst","selectLast","toEnd","clampListViewport","changed","getExpandedNav","undefined","nav","scrollDown","maxVisible","expanded","maxOffset","Math","max","scrollUp","scrollPageDown","newPosition","min","scrollPageUp","scrollToTop","scrollToBottom","toggleExpand","visibleCountWhenExpanded","collapse","signalExit","callback","shouldExit","exitCallback","reset","dispose","header","bufferVersion","listeners","forEach","l","options","showStatusBar","Set","subscribe","listener","add","delete","getSnapshot","getRunningProcesses","filter","getCompletedProcesses","getRunningCount","getMaxGroupLength","getDoneCount","getErrorLineCount","reduce","total","getMode","getSelectedIndex","getExpandedId","getListScrollOffset","viewportOffset","getErrorFooterExpanded","getBufferVersion","getFilterMode","getSearchTerm","getIsSearching","getIsFullscreen","filtered","toLowerCase","getScrollOffset","getHeader","getShowStatusBar","getIsInteractive","every","getShouldExit","getExitCallback","interactive"],"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';\ntype FilterMode = 'all' | 'running' | 'finished' | 'failed';\n\nconst FILTER_CYCLE: FilterMode[] = ['all', 'running', 'finished', 'failed'];\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 private filterMode: FilterMode = 'all';\n private searchTerm = '';\n private isSearching = false;\n private isFullscreen = false;\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 // Uses filtered processes count so selection works correctly with filters\n this.listNav = createNavigator({\n getLength: () => this.getFilteredProcesses().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 getFilterMode = (): FilterMode => this.filterMode;\n getSearchTerm = (): string => this.searchTerm;\n getIsSearching = (): boolean => this.isSearching;\n getIsFullscreen = (): boolean => this.isFullscreen;\n\n // Get processes filtered by current filter mode and search term\n getFilteredProcesses = (): ChildProcess[] => {\n let filtered = this.processes;\n\n // Apply filter mode\n switch (this.filterMode) {\n case 'running':\n filtered = filtered.filter((p) => p.state === 'running');\n break;\n case 'finished':\n filtered = filtered.filter((p) => p.state !== 'running');\n break;\n case 'failed':\n filtered = filtered.filter((p) => p.state === 'error');\n break;\n }\n\n // Apply search term\n if (this.searchTerm) {\n const term = this.searchTerm.toLowerCase();\n filtered = filtered.filter((p) => p.title.toLowerCase().includes(term) || (p.group && p.group.toLowerCase().includes(term)));\n }\n\n return filtered;\n };\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.getFilteredProcesses()[this.listNav.position];\n }\n\n // Filter mode cycling (left/right arrows)\n cycleFilterNext(): void {\n const currentIndex = FILTER_CYCLE.indexOf(this.filterMode);\n this.filterMode = FILTER_CYCLE[(currentIndex + 1) % FILTER_CYCLE.length] as FilterMode;\n // Reset selection when filter changes\n this.listNav.toStart();\n // Collapse any expanded process when filter changes\n this.expandedId = null;\n this.notify();\n }\n\n cycleFilterPrev(): void {\n const currentIndex = FILTER_CYCLE.indexOf(this.filterMode);\n this.filterMode = FILTER_CYCLE[(currentIndex - 1 + FILTER_CYCLE.length) % FILTER_CYCLE.length] as FilterMode;\n // Reset selection when filter changes\n this.listNav.toStart();\n // Collapse any expanded process when filter changes\n this.expandedId = null;\n this.notify();\n }\n\n // Search mode\n startSearch(): void {\n this.isSearching = true;\n this.searchTerm = '';\n this.notify();\n }\n\n updateSearchTerm(term: string): void {\n this.searchTerm = term;\n // Reset selection when search changes\n this.listNav.toStart();\n this.notify();\n }\n\n cancelSearch(): void {\n this.isSearching = false;\n this.searchTerm = '';\n // Reset selection\n this.listNav.toStart();\n this.notify();\n }\n\n confirmSearch(): void {\n this.isSearching = false;\n // Keep searchTerm applied, reset selection to first match\n this.listNav.toStart();\n this.notify();\n }\n\n clearSearch(): void {\n this.searchTerm = '';\n this.listNav.toStart();\n this.notify();\n }\n\n // Fullscreen mode (alternate screen buffer)\n enterFullscreen(): void {\n // If not expanded, expand the selected process first\n if (!this.expandedId) {\n const selected = this.getSelectedProcess();\n if (selected) {\n this.expandedId = selected.id;\n }\n }\n if (this.expandedId) {\n this.isFullscreen = true;\n this.notify();\n }\n }\n\n exitFullscreen(visibleCountWhenCollapsed?: number): void {\n this.isFullscreen = false;\n // Also collapse when exiting fullscreen\n this.expandedId = null;\n if (visibleCountWhenCollapsed) {\n this.listNav.clampViewport(visibleCountWhenCollapsed);\n }\n this.notify();\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.filterMode = 'all';\n this.searchTerm = '';\n this.isSearching = false;\n this.isFullscreen = 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":["arrayFind","DEFAULT_COLUMN_WIDTH","LineType","createNavigator","FILTER_CYCLE","ProcessStore","getErrorLines","getFailedProcesses","map","p","processName","group","title","lines","getProcessLines","id","addProcess","process","processWithNav","scrollNav","getLength","getProcessLineCount","wrap","onMove","notify","processes","updateProcess","update","oldProcess","wasRunning","state","isNowComplete","completedIds","includes","isInteractive","isAllComplete","getErrorCount","errorFooterExpanded","appendLines","newLines","concat","getProcess","terminalBuffer","getLines","text","type","stdout","lineCount","length","setMode","mode","listNav","setPosition","getSelectedProcess","getFilteredProcesses","position","cycleFilterNext","currentIndex","indexOf","filterMode","toStart","expandedId","cycleFilterPrev","startSearch","isSearching","searchTerm","updateSearchTerm","term","cancelSearch","confirmSearch","clearSearch","enterFullscreen","selected","isFullscreen","exitFullscreen","visibleCountWhenCollapsed","clampViewport","toggleErrorFooter","expandErrorFooter","selectNext","visibleCount","down","ensureVisible","selectPrev","up","selectPageDown","pageSize","pageDown","selectPageUp","pageUp","selectFirst","selectLast","toEnd","clampListViewport","changed","getExpandedNav","undefined","nav","scrollDown","maxVisible","expanded","maxOffset","Math","max","scrollUp","scrollPageDown","newPosition","min","scrollPageUp","scrollToTop","scrollToBottom","toggleExpand","visibleCountWhenExpanded","collapse","signalExit","callback","shouldExit","exitCallback","reset","dispose","header","bufferVersion","listeners","forEach","l","options","showStatusBar","Set","subscribe","listener","add","delete","getSnapshot","getRunningProcesses","filter","getCompletedProcesses","getRunningCount","getMaxGroupLength","getDoneCount","getErrorLineCount","reduce","total","getMode","getSelectedIndex","getExpandedId","getListScrollOffset","viewportOffset","getErrorFooterExpanded","getBufferVersion","getFilterMode","getSearchTerm","getIsSearching","getIsFullscreen","filtered","toLowerCase","getScrollOffset","getHeader","getShowStatusBar","getIsInteractive","every","getShouldExit","getExitCallback","interactive"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spawn-term",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Formats spawn with for terminal grouping",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"spawn",
|
|
@@ -43,23 +43,23 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@xterm/headless": "^5.5.0",
|
|
46
|
-
"cross-spawn-cb": "^
|
|
47
|
-
"install-module-linked": "^1.3.
|
|
48
|
-
"on-one": "^1.0.
|
|
49
|
-
"queue-cb": "^1.
|
|
46
|
+
"cross-spawn-cb": "^3.0.0",
|
|
47
|
+
"install-module-linked": "^1.3.16",
|
|
48
|
+
"on-one": "^1.0.0",
|
|
49
|
+
"queue-cb": "^1.0.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@types/mocha": "
|
|
53
|
-
"@types/node": "
|
|
52
|
+
"@types/mocha": "*",
|
|
53
|
+
"@types/node": "*",
|
|
54
54
|
"@types/react": "^19.2.7",
|
|
55
55
|
"cr": "^0.1.0",
|
|
56
56
|
"ink": "^6.5.1",
|
|
57
57
|
"is-version": "^1.0.9",
|
|
58
|
-
"node-version-use": "
|
|
59
|
-
"pinkie-promise": "
|
|
58
|
+
"node-version-use": "*",
|
|
59
|
+
"pinkie-promise": "*",
|
|
60
60
|
"react": "^19.2.3",
|
|
61
|
-
"ts-dev-stack": "
|
|
62
|
-
"tsds-config": "
|
|
61
|
+
"ts-dev-stack": "*",
|
|
62
|
+
"tsds-config": "*"
|
|
63
63
|
},
|
|
64
64
|
"engines": {
|
|
65
65
|
"node": ">=0.8"
|