node-automator 1.4.9 → 1.4.11
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/commands/backup.js +6 -1
- package/commands/compress.js +1 -0
- package/commands/mgr.js +2 -0
- package/commands/word2txt.js +42 -0
- package/index.js +19 -2
- package/package.json +2 -1
- package/utils/interaction_tool.js +6 -6
- package/utils/request_tool.js +10 -8
- package/utils/selection_tool.js +40 -32
- package/utils/shell_tool.js +4 -3
package/commands/backup.js
CHANGED
|
@@ -7,7 +7,8 @@ const fs = require("fs");
|
|
|
7
7
|
const path = require("path");
|
|
8
8
|
const {
|
|
9
9
|
success,
|
|
10
|
-
error
|
|
10
|
+
error,
|
|
11
|
+
warn
|
|
11
12
|
} = require('../utils/log_tool');
|
|
12
13
|
const {
|
|
13
14
|
parse,
|
|
@@ -50,6 +51,10 @@ class BackupCommand extends BaseCommand {
|
|
|
50
51
|
backupData = backupData[key];
|
|
51
52
|
}
|
|
52
53
|
}
|
|
54
|
+
if (backupData === undefined) {
|
|
55
|
+
warn(`未找到 ${filename} 的 ${sourceKeys} 字段`)
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
53
58
|
if (backupFormat) {
|
|
54
59
|
backupData = await stringify(backupData, backupFormat);
|
|
55
60
|
}
|
package/commands/compress.js
CHANGED
|
@@ -10,6 +10,7 @@ class CompressCommand extends BaseCommand {
|
|
|
10
10
|
const dst = get_full_path(data.dst, "FILE");
|
|
11
11
|
const options = data.options || {};
|
|
12
12
|
let image = await Jimp.read(src);
|
|
13
|
+
image.scale(options.scale || 1);
|
|
13
14
|
image.quality(options.quality || 80);
|
|
14
15
|
await image.writeAsync(dst);
|
|
15
16
|
}
|
package/commands/mgr.js
CHANGED
|
@@ -118,6 +118,7 @@ const { DeobfuscateCommand } = require('./deobfuscate');
|
|
|
118
118
|
const { AliOssCommand } = require('./ali_oss');
|
|
119
119
|
const { BackupCommand } = require('./backup');
|
|
120
120
|
const { CompressCommand } = require('./compress');
|
|
121
|
+
const { Word2txtCommand } = require('./word2txt');
|
|
121
122
|
|
|
122
123
|
const globalData = {
|
|
123
124
|
"executed_cfg": [], // 执行过的配置文件
|
|
@@ -479,6 +480,7 @@ function init() {
|
|
|
479
480
|
register("ali_oss", AliOssCommand, false);
|
|
480
481
|
register("backup", BackupCommand, false);
|
|
481
482
|
register("compress", CompressCommand, false);
|
|
483
|
+
register("word2txt", Word2txtCommand, false);
|
|
482
484
|
}
|
|
483
485
|
|
|
484
486
|
module.exports = {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const {
|
|
2
|
+
get_fst_file
|
|
3
|
+
} = require('../utils/file_tool');
|
|
4
|
+
const {
|
|
5
|
+
BaseCommand
|
|
6
|
+
} = require("./base");
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const mammoth = require('mammoth');
|
|
9
|
+
|
|
10
|
+
class Word2txtCommand extends BaseCommand {
|
|
11
|
+
async execute() {
|
|
12
|
+
const data = this.selfData;
|
|
13
|
+
const wordFilePath = get_fst_file(data.src);
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
// 读取 Word 文件
|
|
16
|
+
fs.readFile(wordFilePath, (err, data) => {
|
|
17
|
+
if (err) {
|
|
18
|
+
reject(err);
|
|
19
|
+
return console.error("读取文件时出错:", err);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 将 Word 文件转换为纯文本
|
|
23
|
+
mammoth.extractRawText({
|
|
24
|
+
buffer: data
|
|
25
|
+
})
|
|
26
|
+
.then((result) => {
|
|
27
|
+
const text = result.value; // 纯文本内容
|
|
28
|
+
console.log("转换后的文本内容:", text);
|
|
29
|
+
resolve(text);
|
|
30
|
+
})
|
|
31
|
+
.catch((err) => {
|
|
32
|
+
console.error("转换过程中出错:", err);
|
|
33
|
+
reject(err);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
Word2txtCommand,
|
|
42
|
+
};
|
package/index.js
CHANGED
|
@@ -70,11 +70,18 @@ async function getCfgs() {
|
|
|
70
70
|
async function MainProcess() {
|
|
71
71
|
const enableTimer = argv.ENABLE_TIMER;
|
|
72
72
|
const timerInterval = argv.TIMER_INTERVAL;
|
|
73
|
+
const estimateTime = +argv.ESTIMATE_TIME;
|
|
73
74
|
let beginTime = Date.now();
|
|
74
75
|
let timer;
|
|
75
76
|
if (enableTimer && timerInterval) {
|
|
76
77
|
timer = setInterval(() => {
|
|
77
|
-
|
|
78
|
+
const elapsedTime = Date.now() - beginTime;
|
|
79
|
+
if (!estimateTime) {
|
|
80
|
+
info(`\r[${formatTimestampMillisec(Date.now())}] 任务已运行 ${formatTimeInMillisec(elapsedTime, "hh:mm:ss")} ${clear_line_end}`, "");
|
|
81
|
+
} else {
|
|
82
|
+
const estimateLeft = Math.max(0, estimateTime - elapsedTime);
|
|
83
|
+
info(`\r[${formatTimestampMillisec(Date.now())}] 任务已运行 ${formatTimeInMillisec(elapsedTime, "hh:mm:ss")}, 预计剩余 ${formatTimeInMillisec(estimateLeft, "hh:mm:ss")} ${clear_line_end}`, "");
|
|
84
|
+
}
|
|
78
85
|
}, timerInterval);
|
|
79
86
|
}
|
|
80
87
|
let lastError = null;
|
|
@@ -98,7 +105,17 @@ async function MainProcess() {
|
|
|
98
105
|
if (enableTimer) {
|
|
99
106
|
clearInterval(timer);
|
|
100
107
|
info("")
|
|
101
|
-
|
|
108
|
+
const costTime = Date.now() - beginTime;
|
|
109
|
+
let timeLog = `任务总耗时 ${formatTimeInMillisec(costTime, "hh:mm:ss")}`;
|
|
110
|
+
if (estimateTime) {
|
|
111
|
+
const offsetTime = costTime - estimateTime;
|
|
112
|
+
if (offsetTime > 0) {
|
|
113
|
+
timeLog += `, 比预期慢了 ${formatTimeInMillisec(offsetTime, "hh:mm:ss")}`;
|
|
114
|
+
} else {
|
|
115
|
+
timeLog += `, 比预期快了 ${formatTimeInMillisec(-offsetTime, "hh:mm:ss")}`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
success(`>>> ${timeLog} <<<`, undefined, undefined, true);
|
|
102
119
|
}
|
|
103
120
|
|
|
104
121
|
let code = lastError ? (getLastErrorCode() || 1) : 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-automator",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.11",
|
|
4
4
|
"description": "Execute automation with yaml configuration(compatible with json)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"log4js": "^6.3.0",
|
|
42
42
|
"luaparse": "^0.3.1",
|
|
43
43
|
"mail-watcher": "^0.6.1",
|
|
44
|
+
"mammoth": "^1.8.0",
|
|
44
45
|
"markdown-table": "^2.0.0",
|
|
45
46
|
"mysql": "^2.18.1",
|
|
46
47
|
"node-localstorage": "^2.1.6",
|
|
@@ -83,7 +83,7 @@ async function pause(prompt = "", countdown) {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
|
-
let timeout
|
|
86
|
+
let timeout = 0;
|
|
87
87
|
if (needCountDown) {
|
|
88
88
|
timeout = setInterval(() => {
|
|
89
89
|
leftTime -= 1;
|
|
@@ -181,22 +181,22 @@ function showOptions(viewOptions, filteredViewOptions, selectedIndices, focusedI
|
|
|
181
181
|
}, 0);
|
|
182
182
|
clearLine();
|
|
183
183
|
info(`当前选择: ${typeof selectedIndices === "number" ? (selectedIndices == -1 ? 0 : 1) : selectedIndices.length} / ${filteredViewOptions.length}`);
|
|
184
|
-
write(`${begIndex == 0 ? "" : "▲"['magenta']
|
|
184
|
+
write(`${begIndex == 0 ? "" : "▲"['magenta']}${clear_line_end}\n`);
|
|
185
185
|
for (let i = 0; i < numPerPage; ++i) {
|
|
186
|
-
|
|
186
|
+
// for (let index = begIndex; index < begIndex + numShow; index++) {
|
|
187
187
|
let index = begIndex + i;
|
|
188
188
|
let viewOption = filteredViewOptions[index];
|
|
189
189
|
if (viewOption == undefined) {
|
|
190
190
|
write(clear_line_end + "\n");
|
|
191
191
|
continue;
|
|
192
192
|
}
|
|
193
|
-
let viewOptionStr = `${alignStr(viewOption.
|
|
193
|
+
let viewOptionStr = `${alignStr(viewOption.showKey, maxKeyLength, { alignment: alignment })} - ${viewOption.value?.toString().replace(new RegExp(LINE_EXPRESSION, "g"), "")}`;
|
|
194
194
|
let indicator;
|
|
195
195
|
let optionColor;
|
|
196
196
|
let selected = selectedIndices === index || selectedIndices instanceof Array && selectedIndices.includes(index);
|
|
197
197
|
let focused = focusedIndex === index;
|
|
198
198
|
let filtered = filteredViewOptions && filteredViewOptions.length != filteredViewOptions.length && filteredViewOptions.includes(viewOption);
|
|
199
|
-
indicator = focused ? `${indicator_char} `
|
|
199
|
+
indicator = focused ? `${indicator_char} `[selectColor] : " ";
|
|
200
200
|
if (selected) {
|
|
201
201
|
optionColor = selectColor;
|
|
202
202
|
} else if (filtered) {
|
|
@@ -215,7 +215,7 @@ function showOptions(viewOptions, filteredViewOptions, selectedIndices, focusedI
|
|
|
215
215
|
write(`${indicator}${preview[optionColor]}`);
|
|
216
216
|
write('\n');
|
|
217
217
|
}
|
|
218
|
-
write(`${begIndex + numShow >= filteredViewOptions.length ? "" : "▼"['magenta']
|
|
218
|
+
write(`${begIndex + numShow >= filteredViewOptions.length ? "" : "▼"['magenta']}${clear_line_end}\n`);
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
module.exports = {
|
package/utils/request_tool.js
CHANGED
|
@@ -10,7 +10,7 @@ const { hash } = require('./hash_tool');
|
|
|
10
10
|
async function doRequest(data) {
|
|
11
11
|
const request = require("request");
|
|
12
12
|
const request_progress = require("request-progress");
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
let url = data.src || data?.target?.url;
|
|
15
15
|
let urlObj = new URL(url);
|
|
16
16
|
/** 是否启用 http 缓存 */
|
|
@@ -112,7 +112,7 @@ async function doRequest(data) {
|
|
|
112
112
|
resolve(res.headers);
|
|
113
113
|
} else {
|
|
114
114
|
resolve(result);
|
|
115
|
-
}
|
|
115
|
+
}
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
});
|
|
@@ -121,14 +121,16 @@ async function doRequest(data) {
|
|
|
121
121
|
});
|
|
122
122
|
request_progress(
|
|
123
123
|
req.on('progress', function (state) {
|
|
124
|
-
|
|
124
|
+
sizeTotal = state.size.total;
|
|
125
|
+
if (!quiet) {
|
|
125
126
|
hasProgress = true;
|
|
126
|
-
!quiet && progress(state.size.transferred, state.size.total, {
|
|
127
|
-
desc: `请求中...(elapsed: ${transform_tool.formatTimeInSec(state.time.elapsed)}, speed: ${transform_tool.formatByteSize(state.speed)}/s, ETA: ${transform_tool.formatTimeInSec(state.time.remaining)})`,
|
|
128
|
-
format_bytes: true,
|
|
129
|
-
color: "cyan"
|
|
130
|
-
}, true);
|
|
131
127
|
}
|
|
128
|
+
!quiet && progress(state.size.transferred, state.size.total, {
|
|
129
|
+
desc: `请求中...(elapsed: ${transform_tool.formatTimeInSec(state.time.elapsed)}, speed: ${transform_tool.formatByteSize(state.speed)}/s, ETA: ${transform_tool.formatTimeInSec(state.time.remaining)})`,
|
|
130
|
+
format_bytes: true,
|
|
131
|
+
color: "cyan"
|
|
132
|
+
}, true);
|
|
133
|
+
}
|
|
132
134
|
)
|
|
133
135
|
);
|
|
134
136
|
}
|
package/utils/selection_tool.js
CHANGED
|
@@ -14,6 +14,7 @@ async function select(content, data) {
|
|
|
14
14
|
info("");
|
|
15
15
|
// 支持数组以及普通对象
|
|
16
16
|
let optionKeys = Object.keys(content);
|
|
17
|
+
const isContentArray = Array.isArray(content);
|
|
17
18
|
// 过滤
|
|
18
19
|
let keyFilterRegExp =
|
|
19
20
|
data.key_filter_pattern && new RegExp(data.key_filter_pattern);
|
|
@@ -34,8 +35,10 @@ async function select(content, data) {
|
|
|
34
35
|
const options = content;
|
|
35
36
|
const viewOptions = optionKeys.map((optionKey, index) => {
|
|
36
37
|
let optionValue = options[optionKey];
|
|
38
|
+
const showKey = isContentArray ? (+optionKey + 1) : optionKey;
|
|
37
39
|
if (data.preview_handler) {
|
|
38
40
|
return {
|
|
41
|
+
showKey,
|
|
39
42
|
key: optionKey,
|
|
40
43
|
value: eval_code(data.preview_handler)(
|
|
41
44
|
optionValue,
|
|
@@ -45,16 +48,17 @@ async function select(content, data) {
|
|
|
45
48
|
};
|
|
46
49
|
}
|
|
47
50
|
return {
|
|
51
|
+
showKey,
|
|
48
52
|
key: optionKey,
|
|
49
53
|
value: data.preview
|
|
50
54
|
? toArray(data.preview)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
.map((k, i) =>
|
|
56
|
+
i == -1 ? `${k}:${optionValue[k]}` : optionValue[k]
|
|
57
|
+
)
|
|
58
|
+
.join(" | ")
|
|
55
59
|
: typeof optionValue === "object"
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
? JSON.stringify(optionValue)
|
|
61
|
+
: optionValue,
|
|
58
62
|
};
|
|
59
63
|
});
|
|
60
64
|
let filteredViewOptions = viewOptions;
|
|
@@ -127,7 +131,7 @@ async function select(content, data) {
|
|
|
127
131
|
warn(err);
|
|
128
132
|
}
|
|
129
133
|
}
|
|
130
|
-
let numPerPage = OPTION_PAGE_SIZE;
|
|
134
|
+
let numPerPage = data.OPTION_PAGE_SIZE || OPTION_PAGE_SIZE;
|
|
131
135
|
function restrictFocusedIndex() {
|
|
132
136
|
if (focusedIndex < 0) {
|
|
133
137
|
focusedIndex = 0;
|
|
@@ -231,7 +235,7 @@ async function select(content, data) {
|
|
|
231
235
|
);
|
|
232
236
|
focusedIndex = viewOptions.indexOf(
|
|
233
237
|
filteredViewOptions[
|
|
234
|
-
|
|
238
|
+
Math.min(filterIdx + 1, filteredViewOptions.length - 1)
|
|
235
239
|
]
|
|
236
240
|
);
|
|
237
241
|
restrictFocusedIndex();
|
|
@@ -284,15 +288,15 @@ async function select(content, data) {
|
|
|
284
288
|
filteredViewOptions = !inputParts
|
|
285
289
|
? viewOptions
|
|
286
290
|
: viewOptions.filter((option, i) => {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
});
|
|
291
|
+
let valueStr = JSON.stringify(option.value);
|
|
292
|
+
return inputParts.some((part) => {
|
|
293
|
+
return (
|
|
294
|
+
part == i ||
|
|
295
|
+
part == option.key ||
|
|
296
|
+
valueStr.indexOf(part) != -1
|
|
297
|
+
);
|
|
295
298
|
});
|
|
299
|
+
});
|
|
296
300
|
if (filteredViewOptions.length) {
|
|
297
301
|
focusedIndex = viewOptions.indexOf(filteredViewOptions[0]);
|
|
298
302
|
}
|
|
@@ -316,6 +320,7 @@ async function multiSelect(content, data) {
|
|
|
316
320
|
info("");
|
|
317
321
|
// 支持数组以及普通对象
|
|
318
322
|
let optionKeys = Object.keys(content);
|
|
323
|
+
const isContentArray = Array.isArray(content);
|
|
319
324
|
// 过滤
|
|
320
325
|
let keyFilterRegExp =
|
|
321
326
|
data.key_filter_pattern && new RegExp(data.key_filter_pattern);
|
|
@@ -336,8 +341,10 @@ async function multiSelect(content, data) {
|
|
|
336
341
|
const options = content;
|
|
337
342
|
const viewOptions = optionKeys.map((optionKey, index) => {
|
|
338
343
|
let optionValue = options[optionKey];
|
|
344
|
+
const showKey = isContentArray ? (1 + optionKey) : optionKey;
|
|
339
345
|
if (data.preview_handler) {
|
|
340
346
|
return {
|
|
347
|
+
showKey,
|
|
341
348
|
key: optionKey,
|
|
342
349
|
value: eval_code(data.preview_handler)(
|
|
343
350
|
optionValue,
|
|
@@ -347,16 +354,17 @@ async function multiSelect(content, data) {
|
|
|
347
354
|
};
|
|
348
355
|
}
|
|
349
356
|
return {
|
|
357
|
+
showKey,
|
|
350
358
|
key: optionKey,
|
|
351
359
|
value: data.preview
|
|
352
360
|
? toArray(data.preview)
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
361
|
+
.map((k, i) =>
|
|
362
|
+
i == -1 ? `${k}:${optionValue[k]}` : optionValue[k]
|
|
363
|
+
)
|
|
364
|
+
.join(" | ")
|
|
357
365
|
: typeof optionValue === "object"
|
|
358
|
-
|
|
359
|
-
|
|
366
|
+
? JSON.stringify(optionValue)
|
|
367
|
+
: optionValue,
|
|
360
368
|
};
|
|
361
369
|
});
|
|
362
370
|
let filteredViewOptions = viewOptions;
|
|
@@ -365,7 +373,7 @@ async function multiSelect(content, data) {
|
|
|
365
373
|
let focusedIndex = 0;
|
|
366
374
|
let confirmEmpty = false;
|
|
367
375
|
let selectedIndices = [];
|
|
368
|
-
let numPerPage = OPTION_PAGE_SIZE;
|
|
376
|
+
let numPerPage = data.OPTION_PAGE_SIZE || OPTION_PAGE_SIZE;
|
|
369
377
|
function restrictFocusedIndex() {
|
|
370
378
|
if (focusedIndex < 0) {
|
|
371
379
|
focusedIndex = 0;
|
|
@@ -476,7 +484,7 @@ async function multiSelect(content, data) {
|
|
|
476
484
|
);
|
|
477
485
|
focusedIndex = viewOptions.indexOf(
|
|
478
486
|
filteredViewOptions[
|
|
479
|
-
|
|
487
|
+
Math.min(filterIdx + 1, filteredViewOptions.length - 1)
|
|
480
488
|
]
|
|
481
489
|
);
|
|
482
490
|
restrictFocusedIndex();
|
|
@@ -557,15 +565,15 @@ async function multiSelect(content, data) {
|
|
|
557
565
|
filteredViewOptions = !inputParts
|
|
558
566
|
? viewOptions
|
|
559
567
|
: viewOptions.filter((option, i) => {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
});
|
|
568
|
+
let valueStr = JSON.stringify(option.value);
|
|
569
|
+
return inputParts.some((part) => {
|
|
570
|
+
return (
|
|
571
|
+
part == i ||
|
|
572
|
+
part == option.key ||
|
|
573
|
+
valueStr.indexOf(part) != -1
|
|
574
|
+
);
|
|
568
575
|
});
|
|
576
|
+
});
|
|
569
577
|
if (inputStr && filteredViewOptions.length) {
|
|
570
578
|
focusedIndex = viewOptions.indexOf(filteredViewOptions[0]);
|
|
571
579
|
}
|
package/utils/shell_tool.js
CHANGED
|
@@ -64,6 +64,7 @@ async function exec_shell(data) {
|
|
|
64
64
|
let results = [];
|
|
65
65
|
let errors = [];
|
|
66
66
|
let encoding = data.encoding || "cp936";
|
|
67
|
+
let raw_output = encoding == "raw";
|
|
67
68
|
!quiet && whisper(`cmd:[${cmd}] cwd:${data.cwd} inputs:${data.inputs}`);
|
|
68
69
|
options.stdio = ["pipe", capture_stdout ? "pipe" : process.stdout, "pipe"];
|
|
69
70
|
const child = child_process.spawn(cmd[0], cmd.slice(1), options);
|
|
@@ -71,7 +72,7 @@ async function exec_shell(data) {
|
|
|
71
72
|
child.stdout.on("data", (chunk) => {
|
|
72
73
|
results.push(chunk);
|
|
73
74
|
if (instant_stdout) {
|
|
74
|
-
warn(iconv.decode(chunk, encoding));
|
|
75
|
+
warn(!raw_output ? iconv.decode(chunk, encoding) : chunk.toString());
|
|
75
76
|
}
|
|
76
77
|
});
|
|
77
78
|
}
|
|
@@ -98,7 +99,7 @@ async function exec_shell(data) {
|
|
|
98
99
|
// child.on('close', code => {
|
|
99
100
|
child.on('exit', code => {
|
|
100
101
|
if (!data.ignore_code && code != 0) {
|
|
101
|
-
let errMsg = iconv.decode(Buffer.concat(errors), encoding);
|
|
102
|
+
let errMsg = !raw_output ? iconv.decode(Buffer.concat(errors), encoding) : Buffer.concat(errors).toString();
|
|
102
103
|
let isAcceptableErrors = errMsg && acceptableErrors.some(err => {
|
|
103
104
|
return errMsg.indexOf(err) >= 0;
|
|
104
105
|
});
|
|
@@ -107,7 +108,7 @@ async function exec_shell(data) {
|
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
110
|
if (results.length) {
|
|
110
|
-
let result = iconv.decode(Buffer.concat(results), encoding);
|
|
111
|
+
let result = !raw_output ? iconv.decode(Buffer.concat(results), encoding) : Buffer.concat(results);
|
|
111
112
|
if (data.trim) {
|
|
112
113
|
result = result.trim();
|
|
113
114
|
}
|