visual-exec 0.1.13 → 0.2.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.
@@ -0,0 +1,4 @@
1
+ import VisualLogger from "visual-logger";
2
+ export declare function getDefaultLogger(): VisualLogger;
3
+ export default getDefaultLogger;
4
+ //# sourceMappingURL=get-default-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-default-logger.d.ts","sourceRoot":"","sources":["../src/get-default-logger.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAKzC,wBAAgB,gBAAgB,IAAI,YAAY,CAU/C;AAED,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getDefaultLogger = getDefaultLogger;
7
+ const visual_logger_1 = __importDefault(require("visual-logger"));
8
+ const ci_info_1 = require("ci-info");
9
+ let logger = null;
10
+ function getDefaultLogger() {
11
+ if (!logger) {
12
+ logger = new visual_logger_1.default();
13
+ if (ci_info_1.isCI) {
14
+ logger.info("visual-exec: CI env detected");
15
+ logger.setItemType("none");
16
+ }
17
+ }
18
+ return logger;
19
+ }
20
+ exports.default = getDefaultLogger;
21
+ //# sourceMappingURL=get-default-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-default-logger.js","sourceRoot":"","sources":["../src/get-default-logger.ts"],"names":[],"mappings":";;;;;AAKA,4CAUC;AAfD,kEAAyC;AACzC,qCAA+B;AAE/B,IAAI,MAAM,GAAwB,IAAI,CAAC;AAEvC,SAAgB,gBAAgB;IAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,IAAI,uBAAY,EAAE,CAAC;QAE5B,IAAI,cAAI,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;YAC5C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,kBAAe,gBAAgB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { VisualExec, VisualExecOptions } from "./visual-exec";
2
+ export { getDefaultLogger } from "./get-default-logger";
3
+ export { VisualExec as default } from "./visual-exec";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,UAAU,IAAI,OAAO,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = exports.getDefaultLogger = exports.VisualExec = void 0;
4
+ var visual_exec_1 = require("./visual-exec");
5
+ Object.defineProperty(exports, "VisualExec", { enumerable: true, get: function () { return visual_exec_1.VisualExec; } });
6
+ var get_default_logger_1 = require("./get-default-logger");
7
+ Object.defineProperty(exports, "getDefaultLogger", { enumerable: true, get: function () { return get_default_logger_1.getDefaultLogger; } });
8
+ var visual_exec_2 = require("./visual-exec");
9
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return visual_exec_2.VisualExec; } });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,6CAA8D;AAArD,yGAAA,UAAU,OAAA;AACnB,2DAAwD;AAA/C,sHAAA,gBAAgB,OAAA;AACzB,6CAAsD;AAA7C,sGAAA,UAAU,OAAW"}
@@ -0,0 +1,70 @@
1
+ import VisualLogger from "visual-logger";
2
+ export interface VisualExecOptions {
3
+ /** The command to execute */
4
+ command: string;
5
+ /** Working directory for the command */
6
+ cwd?: string;
7
+ /** Visual logger instance to use */
8
+ visualLogger?: VisualLogger;
9
+ /** Spinner style to use */
10
+ spinner?: any;
11
+ /** Title displayed during execution */
12
+ displayTitle?: string;
13
+ /** Label used in log messages */
14
+ logLabel?: string;
15
+ /** Label used in output messages */
16
+ outputLabel?: string;
17
+ /** Log level for output (default: "verbose") */
18
+ outputLevel?: string;
19
+ /** Maximum buffer size for stdout/stderr (default: 10MB) */
20
+ maxBuffer?: number;
21
+ /** Force stderr output to be logged as error (default: true) */
22
+ forceStderr?: boolean;
23
+ /** Regex or boolean to check stdout for error patterns (default: true) */
24
+ checkStdoutError?: boolean | RegExp;
25
+ }
26
+ interface ExecOutput {
27
+ stdout: string;
28
+ stderr: string;
29
+ }
30
+ interface ExecError extends Error {
31
+ output?: ExecOutput;
32
+ }
33
+ interface ChildProcess {
34
+ stdout: NodeJS.ReadableStream;
35
+ stderr: NodeJS.ReadableStream;
36
+ promise: Promise<ExecOutput>;
37
+ }
38
+ export declare class VisualExec {
39
+ private _title;
40
+ private _logLabel;
41
+ private _outputLabel;
42
+ private _command;
43
+ private _cwd;
44
+ private _logger;
45
+ private _outputLevel;
46
+ private _spinner;
47
+ private _maxBuffer;
48
+ private _forceStderr;
49
+ private _checkStdoutError;
50
+ private _startTime;
51
+ private _stdoutKey?;
52
+ private _stderrKey?;
53
+ private _updateStdout?;
54
+ private _updateStderr?;
55
+ private _child?;
56
+ constructor(options: VisualExecOptions);
57
+ private _makeTitle;
58
+ private _updateDigest;
59
+ show(child: ChildProcess): Promise<ExecOutput>;
60
+ logResult(err: ExecError | null, output?: ExecOutput): void;
61
+ checkForErrors(text: string): RegExpMatchArray | null;
62
+ /**
63
+ * Log the final output. Can be overridden to customize output handling.
64
+ * Set to a no-op function to suppress output logging.
65
+ */
66
+ logFinalOutput(err: ExecError | null, output: ExecOutput): void;
67
+ execute(command?: string): Promise<ExecOutput>;
68
+ }
69
+ export default VisualExec;
70
+ //# sourceMappingURL=visual-exec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-exec.d.ts","sourceRoot":"","sources":["../src/visual-exec.ts"],"names":[],"mappings":"AAGA,OAAO,YAAY,MAAM,eAAe,CAAC;AAUzC,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,2BAA2B;IAC3B,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CACrC;AAOD,UAAU,UAAU;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,SAAU,SAAQ,KAAK;IAC/B,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;CAC9B;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,iBAAiB,CAAmB;IAC5C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAC,CAAwB;IAC9C,OAAO,CAAC,aAAa,CAAC,CAAwB;IAC9C,OAAO,CAAC,MAAM,CAAC,CAAe;gBAElB,OAAO,EAAE,iBAAiB;IAgCtC,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,aAAa;IAmDrB,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC;IAsC9C,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI;IAoB3D,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAQrD;;;OAGG;IACH,cAAc,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IA2B/D,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CAc/C;AAED,eAAe,UAAU,CAAC"}
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.VisualExec = void 0;
7
+ const xsh_1 = __importDefault(require("xsh"));
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const get_default_logger_1 = require("./get-default-logger");
10
+ const visual_logger_1 = __importDefault(require("visual-logger"));
11
+ const has_ansi_1 = __importDefault(require("has-ansi"));
12
+ const strip_ansi_1 = __importDefault(require("strip-ansi"));
13
+ // Set xsh to use native Promise
14
+ xsh_1.default.Promise = Promise;
15
+ const ONE_MB = 1024 * 1024;
16
+ const TEN_MB = 10 * ONE_MB;
17
+ class VisualExec {
18
+ constructor(options) {
19
+ const { command, cwd = process.cwd(), visualLogger, spinner = visual_logger_1.default.spinners[1], displayTitle, logLabel, outputLabel, outputLevel = "verbose", maxBuffer = TEN_MB, forceStderr = true, checkStdoutError = true } = options;
20
+ this._title = displayTitle || this._makeTitle(command);
21
+ this._logLabel = logLabel || this._title;
22
+ this._outputLabel = outputLabel || this._title;
23
+ this._command = command;
24
+ this._cwd = cwd || process.cwd();
25
+ this._logger = visualLogger || (0, get_default_logger_1.getDefaultLogger)();
26
+ this._outputLevel = outputLevel;
27
+ this._spinner = spinner;
28
+ this._maxBuffer = maxBuffer;
29
+ this._forceStderr = forceStderr;
30
+ this._checkStdoutError =
31
+ checkStdoutError === true
32
+ ? /error|warn|fatal|unhandled|reject|exception|failure|fail|failed/i
33
+ : checkStdoutError;
34
+ this._startTime = Date.now();
35
+ }
36
+ _makeTitle(command) {
37
+ if (typeof command !== "string") {
38
+ command = "user command";
39
+ }
40
+ return `Running ${command}`;
41
+ }
42
+ _updateDigest(item, buf) {
43
+ const newBuf = item.buf + buf;
44
+ const lines = newBuf
45
+ .split("\n")
46
+ .map(x => x && x.trim())
47
+ .filter(x => x);
48
+ const stripLines = lines.map(x => ((0, has_ansi_1.default)(x) ? (0, strip_ansi_1.default)(x) : x));
49
+ let length = 0;
50
+ // gather as many lines from the end as possible that will fit in a single line, using
51
+ // strings without ansi code to get real length
52
+ let ix = stripLines.length - 1;
53
+ for (; ix >= 0; ix--) {
54
+ const line = stripLines[ix];
55
+ if (line) {
56
+ if (length + line.length < 100) {
57
+ length += line.length;
58
+ }
59
+ else {
60
+ break;
61
+ }
62
+ }
63
+ }
64
+ let msgs = ix >= 0 ? lines.slice(ix + 1) : lines;
65
+ if (msgs.length === 0) {
66
+ // even the last line is too long, save it, and display last line as is
67
+ item.buf = lines[lines.length - 1] || "";
68
+ // set some reasonable limit to avoid visual digest getting clobberred
69
+ if (item.buf.length > 120) {
70
+ // truncate stripped line only to avoid breaking ansi code
71
+ item.buf = stripLines[stripLines.length - 1].substr(0, 100);
72
+ }
73
+ msgs = [item.buf];
74
+ }
75
+ else {
76
+ item.buf = msgs.join("\n");
77
+ }
78
+ if (buf.endsWith("\n")) {
79
+ item.buf += "\n";
80
+ }
81
+ this._logger.updateItem(item.name, {
82
+ msg: msgs.join(chalk_1.default.blue.inverse("\\n")),
83
+ _save: false,
84
+ _render: false
85
+ });
86
+ }
87
+ show(child) {
88
+ this._stdoutKey = Symbol("visual-exec-stdout");
89
+ this._stderrKey = Symbol("visual-exec-stderr");
90
+ this._logger.addItem({
91
+ name: this._stdoutKey,
92
+ color: "green",
93
+ display: `=== ${this._title}\nstdout`,
94
+ spinner: this._spinner
95
+ });
96
+ this._logger.addItem({
97
+ name: this._stderrKey,
98
+ color: "red",
99
+ display: `stderr`
100
+ });
101
+ const stdoutDigest = { name: this._stdoutKey, buf: "" };
102
+ const stderrDigest = { name: this._stderrKey, buf: "" };
103
+ this._updateStdout = (buf) => this._updateDigest(stdoutDigest, buf);
104
+ this._updateStderr = (buf) => this._updateDigest(stderrDigest, buf);
105
+ child.stdout.on("data", this._updateStdout);
106
+ child.stderr.on("data", this._updateStderr);
107
+ this._child = child;
108
+ return child.promise
109
+ .catch((err) => {
110
+ this.logResult(err);
111
+ throw err;
112
+ })
113
+ .then((output) => {
114
+ this.logResult(null, output);
115
+ return output;
116
+ });
117
+ }
118
+ logResult(err, output) {
119
+ const child = this._child;
120
+ this._logger.removeItem(this._stdoutKey);
121
+ this._logger.removeItem(this._stderrKey);
122
+ child.stdout.removeListener("data", this._updateStdout);
123
+ child.stderr.removeListener("data", this._updateStderr);
124
+ if (err) {
125
+ this._logger.error(`${chalk_1.default.red("Failed")} ${this._logLabel} - ${chalk_1.default.red(err.message)}`);
126
+ output = err.output;
127
+ }
128
+ else {
129
+ const time = ((Date.now() - this._startTime) / 1000).toFixed(2);
130
+ const dispTime = `${chalk_1.default.magenta(time)}secs`;
131
+ this._logger.info(`Done ${this._logLabel} ${dispTime} ${chalk_1.default.green("exit code 0")}`);
132
+ }
133
+ this.logFinalOutput(err, output);
134
+ }
135
+ checkForErrors(text) {
136
+ if (!this._checkStdoutError || !text)
137
+ return null;
138
+ if (this._checkStdoutError instanceof RegExp) {
139
+ return text.match(this._checkStdoutError);
140
+ }
141
+ return null;
142
+ }
143
+ /**
144
+ * Log the final output. Can be overridden to customize output handling.
145
+ * Set to a no-op function to suppress output logging.
146
+ */
147
+ logFinalOutput(err, output) {
148
+ const level = err || (this._forceStderr && output?.stderr) || this.checkForErrors(output?.stdout || "")
149
+ ? "error"
150
+ : this._outputLevel;
151
+ if (!output || (!output.stdout && !output.stderr)) {
152
+ this._logger[level](`${chalk_1.default.green("No output")} from ${this._outputLabel}`);
153
+ return;
154
+ }
155
+ const colorize = (t) => t.replace(/ERR!/g, chalk_1.default.red("ERR!"));
156
+ const logs = [chalk_1.default.green(">>>"), `Start of output from ${this._outputLabel} ===`];
157
+ if (output.stdout) {
158
+ logs.push(`\n${colorize(output.stdout)}`);
159
+ }
160
+ if (output.stderr) {
161
+ logs.push(chalk_1.default.red("\n=== stderr ===\n") + colorize(output.stderr));
162
+ }
163
+ logs.push(chalk_1.default.blue("\n<<<"), `End of output from ${this._outputLabel} ---`);
164
+ this._logger.prefix(false)[level](...logs);
165
+ }
166
+ execute(command) {
167
+ this._startTime = Date.now();
168
+ const child = xsh_1.default.exec({
169
+ silent: true,
170
+ cwd: this._cwd,
171
+ env: Object.assign({}, process.env, { PWD: this._cwd }),
172
+ maxBuffer: this._maxBuffer
173
+ }, command || this._command);
174
+ return this.show(child);
175
+ }
176
+ }
177
+ exports.VisualExec = VisualExec;
178
+ exports.default = VisualExec;
179
+ //# sourceMappingURL=visual-exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-exec.js","sourceRoot":"","sources":["../src/visual-exec.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,20 +1,29 @@
1
1
  {
2
2
  "name": "visual-exec",
3
- "version": "0.1.13",
4
- "description": "Visual shell exec",
5
- "main": "lib/visual-exec.js",
6
- "scripts": {},
3
+ "version": "0.2.0",
4
+ "description": "Visual shell exec with spinners and progress display",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "test": "vitest run",
10
+ "test:watch": "vitest",
11
+ "prepublishOnly": "xrun --serial build test"
12
+ },
7
13
  "repository": {
8
14
  "type": "git",
9
- "url": "https://github.com/jchip/visual-exec.git"
15
+ "url": "https://github.com/jchip/fynpo.git",
16
+ "directory": "packages/visual-exec"
10
17
  },
11
18
  "keywords": [
12
19
  "visual",
13
20
  "shell",
14
- "exec"
21
+ "exec",
22
+ "spinner",
23
+ "progress"
15
24
  ],
16
25
  "files": [
17
- "lib"
26
+ "dist"
18
27
  ],
19
28
  "author": "Joel Chen <joel123@gmail.com>",
20
29
  "license": "Apache-2.0",
@@ -26,6 +35,12 @@
26
35
  "visual-logger": "^1.1.3",
27
36
  "xsh": "^0.4.5"
28
37
  },
38
+ "devDependencies": {
39
+ "@types/node": "^20.0.0",
40
+ "tsx": "^4.20.0",
41
+ "typescript": "^5.9.3",
42
+ "vitest": "^4.0.9"
43
+ },
29
44
  "prettier": {
30
45
  "printWidth": 100,
31
46
  "trailingComma": "none",
@@ -1,19 +0,0 @@
1
- "use strict";
2
-
3
- const VisualLogger = require("visual-logger");
4
- const { isCI } = require("ci-info");
5
-
6
- let logger;
7
- const getLogger = () => {
8
- if (!logger) {
9
- logger = new VisualLogger();
10
-
11
- if (isCI) {
12
- logger.info("visual-exec: CI env detected");
13
- logger.setItemType("none");
14
- }
15
- }
16
- return logger;
17
- };
18
-
19
- module.exports = getLogger;
@@ -1,209 +0,0 @@
1
- "use strict";
2
-
3
- /* eslint-disable no-magic-numbers,no-eval,prefer-template */
4
-
5
- const xsh = require("xsh");
6
- const chalk = require("chalk");
7
- const getDefaultLogger = require("./get-default-logger");
8
- const VisualLogger = require("visual-logger");
9
- const hasAnsi = require("has-ansi");
10
- const stripAnsi = require("strip-ansi");
11
-
12
- xsh.Promise = Promise;
13
-
14
- const ONE_MB = 1024 * 1024;
15
- const TEN_MB = 10 * ONE_MB;
16
-
17
- class VisualExec {
18
- constructor({
19
- command,
20
- cwd = process.cwd(),
21
- visualLogger,
22
- spinner = VisualLogger.spinners[1],
23
- displayTitle = undefined,
24
- logLabel = undefined,
25
- outputLabel = undefined,
26
- outputLevel = "verbose",
27
- maxBuffer = TEN_MB,
28
- forceStderr = true,
29
- checkStdoutError = true
30
- }) {
31
- this._title = displayTitle || this._makeTitle(command);
32
- this._logLabel = logLabel || this._title;
33
- this._outputLabel = outputLabel || this._title;
34
- this._command = command;
35
- this._cwd = cwd || process.cwd();
36
- this._logger = visualLogger || getDefaultLogger();
37
- this._outputLevel = outputLevel;
38
- this._spinner = spinner;
39
- this._maxBuffer = maxBuffer;
40
- this._forceStderr = forceStderr;
41
- this._checkStdoutError =
42
- checkStdoutError === true
43
- ? /error|warn|fatal|unhandled|reject|exception|failure|fail|failed/i
44
- : checkStdoutError;
45
- }
46
-
47
- _makeTitle(command) {
48
- if (typeof command !== "string") {
49
- command = "user command";
50
- }
51
-
52
- return `Running ${command}`;
53
- }
54
-
55
- /* eslint-disable max-statements */
56
- _updateDigest(item, buf) {
57
- const newBuf = item.buf + buf;
58
-
59
- const lines = newBuf
60
- .split("\n")
61
- .map(x => x && x.trim())
62
- .filter(x => x);
63
-
64
- const stripLines = lines.map(x => (hasAnsi(x) ? stripAnsi(x) : x));
65
-
66
- let length = 0;
67
-
68
- // gather as many lines from the end as possible that will fit in a single line, using
69
- // strings without ansi code to get real length
70
- let ix = stripLines.length - 1;
71
- for (; ix >= 0; ix--) {
72
- const line = stripLines[ix];
73
- if (line) {
74
- if (length + line.length < 100) {
75
- length += line.length;
76
- } else {
77
- break;
78
- }
79
- }
80
- }
81
-
82
- let msgs = ix >= 0 ? lines.slice(ix + 1) : lines;
83
- if (msgs.length === 0) {
84
- // even the last line is too long, save it, and display last line as is
85
- item.buf = lines[lines.length - 1] || "";
86
- // set some reasonable limit to avoid visual digest getting clobberred
87
- if (item.buf.length > 120) {
88
- // truncte stripped line only to avoid breaking ansi code
89
- item.buf = stripLines[stripLines.length - 1].substr(0, 100);
90
- }
91
- msgs = [item.buf];
92
- } else {
93
- item.buf = msgs.join("\n");
94
- }
95
-
96
- if (buf.endsWith("\n")) {
97
- item.buf += "\n";
98
- }
99
-
100
- this._logger.updateItem(item.name, {
101
- msg: msgs.join(chalk.blue.inverse("\\n")),
102
- _save: false,
103
- _render: false
104
- });
105
- }
106
-
107
- show(child) {
108
- this._stdoutKey = Symbol("visual-exec-stdout");
109
- this._stderrKey = Symbol("visual-exec-stderr");
110
-
111
- this._logger.addItem({
112
- name: this._stdoutKey,
113
- color: "green",
114
- display: `=== ${this._title}\nstdout`,
115
- spinner: this._spinner
116
- });
117
-
118
- this._logger.addItem({
119
- name: this._stderrKey,
120
- color: "red",
121
- display: `stderr`
122
- });
123
-
124
- const stdoutDigest = { name: this._stdoutKey, buf: "" };
125
- const stderrDigest = { name: this._stderrKey, buf: "" };
126
- this._updateStdout = buf => this._updateDigest(stdoutDigest, buf);
127
- this._updateStderr = buf => this._updateDigest(stderrDigest, buf);
128
-
129
- child.stdout.on("data", this._updateStdout);
130
- child.stderr.on("data", this._updateStderr);
131
-
132
- this._child = child;
133
-
134
- return child.promise
135
- .catch(err => {
136
- this.logResult(err);
137
- throw err;
138
- })
139
- .then(output => {
140
- this.logResult(null, output);
141
- return output;
142
- });
143
- }
144
-
145
- logResult(err, output) {
146
- const child = this._child;
147
-
148
- this._logger.removeItem(this._stdoutKey);
149
- this._logger.removeItem(this._stderrKey);
150
- child.stdout.removeListener("data", this._updateStdout);
151
- child.stderr.removeListener("data", this._updateStderr);
152
-
153
- if (err) {
154
- this._logger.error(`${chalk.red("Failed")} ${this._logLabel} - ${chalk.red(err.message)}`);
155
- output = err.output;
156
- } else {
157
- this._logger.info(`Done ${this._logLabel} ${chalk.green("exit code 0")}`);
158
- }
159
-
160
- this.logFinalOutput(err, output);
161
- }
162
-
163
- checkForErrors(text) {
164
- return this._checkStdoutError && text && text.match(this._checkStdoutError);
165
- }
166
-
167
- logFinalOutput(err, output) {
168
- const level =
169
- err || (this._forceStderr && output.stderr) || this.checkForErrors(output.stdout)
170
- ? "error"
171
- : this._outputLevel;
172
-
173
- if (!output || (!output.stdout && !output.stderr)) {
174
- this._logger[level](`${chalk.green("No output")} from ${this._outputLabel}`);
175
- return;
176
- }
177
-
178
- const colorize = t => t.replace(/ERR!/g, chalk.red("ERR!"));
179
-
180
- const logs = [chalk.green(">>>"), `Start of output from ${this._outputLabel} ===`];
181
-
182
- if (output.stdout) {
183
- logs.push(`\n${colorize(output.stdout)}`);
184
- }
185
-
186
- if (output.stderr) {
187
- logs.push(chalk.red("\n=== stderr ===\n") + colorize(output.stderr));
188
- }
189
-
190
- logs.push(chalk.blue("\n<<<"), `End of output from ${this._outputLabel} ---`);
191
- this._logger.prefix(false)[level](...logs);
192
- }
193
-
194
- execute(command) {
195
- const child = xsh.exec(
196
- {
197
- silent: true,
198
- cwd: this._cwd,
199
- env: Object.assign({}, process.env, { PWD: this._cwd }),
200
- maxBuffer: this._maxBuffer
201
- },
202
- command || this._command
203
- );
204
-
205
- return this.show(child);
206
- }
207
- }
208
-
209
- module.exports = VisualExec;