bunosh 0.3.2 → 0.4.1
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/README.md +225 -328
- package/bunosh.js +173 -48
- package/index.js +3 -3
- package/package.json +1 -1
- package/src/init.js +2 -2
- package/src/io.js +90 -21
- package/src/printer.js +14 -2
- package/src/program.js +321 -21
- package/src/task.js +41 -43
- package/src/tasks/exec.js +14 -2
- package/src/tasks/fetch.js +4 -3
- package/src/tasks/shell.js +37 -5
- package/src/open-editor.js +0 -95
package/bunosh.js
CHANGED
|
@@ -1,63 +1,147 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
// Set up global variables BEFORE any imports
|
|
4
|
+
globalThis._bunoshStartTime = Date.now();
|
|
5
|
+
globalThis._bunoshCommandCompleted = false;
|
|
6
|
+
globalThis._bunoshGlobalTasksExecuted = [];
|
|
7
|
+
globalThis._bunoshGlobalTaskStatus = {
|
|
8
|
+
RUNNING: 'running',
|
|
9
|
+
FAIL: 'fail',
|
|
10
|
+
SUCCESS: 'success',
|
|
11
|
+
WARNING: 'warning'
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// Now import modules
|
|
15
|
+
|
|
2
16
|
import program, { BUNOSHFILE, banner } from "./src/program.js";
|
|
3
17
|
import { existsSync, readFileSync, statSync } from "fs";
|
|
4
18
|
import init from "./src/init.js";
|
|
5
19
|
import path from "path";
|
|
6
|
-
import color from "chalk";
|
|
7
|
-
import './index.js';
|
|
8
|
-
|
|
9
|
-
// Parse --bunoshfile flag before importing tasks
|
|
10
|
-
const bunoshfileIndex = process.argv.indexOf('--bunoshfile');
|
|
11
|
-
let customBunoshfile = null;
|
|
12
|
-
if (bunoshfileIndex !== -1 && bunoshfileIndex + 1 < process.argv.length) {
|
|
13
|
-
customBunoshfile = process.argv[bunoshfileIndex + 1];
|
|
14
|
-
// Remove the flag and its value from process.argv so it doesn't interfere with command parsing
|
|
15
|
-
process.argv.splice(bunoshfileIndex, 2);
|
|
16
|
-
}
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
process.
|
|
21
|
+
|
|
22
|
+
async function main() {
|
|
23
|
+
|
|
24
|
+
// Parse --bunoshfile flag before importing tasks
|
|
25
|
+
const bunoshfileIndex = process.argv.indexOf('--bunoshfile');
|
|
26
|
+
let customBunoshfile = null;
|
|
27
|
+
if (bunoshfileIndex !== -1 && bunoshfileIndex + 1 < process.argv.length) {
|
|
28
|
+
customBunoshfile = process.argv[bunoshfileIndex + 1];
|
|
29
|
+
// Remove the flag and its value from process.argv so it doesn't interfere with command parsing
|
|
30
|
+
process.argv.splice(bunoshfileIndex, 2);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let tasksFile;
|
|
34
|
+
if (customBunoshfile) {
|
|
35
|
+
const resolvedPath = path.isAbsolute(customBunoshfile) ? customBunoshfile : path.resolve(customBunoshfile);
|
|
36
|
+
// If it's a directory, append the default BUNOSHFILE
|
|
37
|
+
if (existsSync(resolvedPath) && statSync(resolvedPath).isDirectory()) {
|
|
38
|
+
tasksFile = path.join(resolvedPath, BUNOSHFILE);
|
|
39
|
+
// Change working directory to the bunoshfile directory
|
|
40
|
+
process.chdir(resolvedPath);
|
|
41
|
+
} else {
|
|
42
|
+
tasksFile = resolvedPath;
|
|
43
|
+
// Change working directory to the bunoshfile's directory
|
|
44
|
+
process.chdir(path.dirname(resolvedPath));
|
|
45
|
+
}
|
|
26
46
|
} else {
|
|
27
|
-
tasksFile =
|
|
28
|
-
|
|
29
|
-
|
|
47
|
+
tasksFile = path.join(process.cwd(), BUNOSHFILE);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Handle -e flag for executing JavaScript code
|
|
51
|
+
const eFlagIndex = process.argv.indexOf('-e');
|
|
52
|
+
if (eFlagIndex !== -1) {
|
|
53
|
+
let jsCode = '';
|
|
54
|
+
|
|
55
|
+
// Check if code is provided as argument
|
|
56
|
+
if (eFlagIndex + 1 < process.argv.length && !process.argv[eFlagIndex + 1].startsWith('-')) {
|
|
57
|
+
jsCode = process.argv[eFlagIndex + 1];
|
|
58
|
+
} else if (!process.stdin.isTTY) {
|
|
59
|
+
// Read from stdin only if it's not a TTY (i.e., it's being piped)
|
|
60
|
+
const chunks = [];
|
|
61
|
+
for await (const chunk of process.stdin) {
|
|
62
|
+
chunks.push(chunk);
|
|
63
|
+
}
|
|
64
|
+
jsCode = Buffer.concat(chunks).toString('utf8').trim();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!jsCode) {
|
|
68
|
+
console.error('No JavaScript code provided');
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
// Import bunosh globals before executing JavaScript
|
|
74
|
+
await import('./index.js');
|
|
75
|
+
|
|
76
|
+
// Make bunosh globals available to the function by creating wrapper functions
|
|
77
|
+
for (const [key, value] of Object.entries(global.bunosh)) {
|
|
78
|
+
if (typeof value === 'function') {
|
|
79
|
+
// For template literal tag functions like exec and shell, create a wrapper
|
|
80
|
+
// that allows them to be called as regular functions with a string
|
|
81
|
+
if (key === 'exec' || key === 'writeToFile') {
|
|
82
|
+
globalThis[key] = (str) => {
|
|
83
|
+
// If called as a regular function with a string, convert to template literal call
|
|
84
|
+
if (typeof str === 'string') {
|
|
85
|
+
return value([str]);
|
|
86
|
+
}
|
|
87
|
+
// Otherwise call normally
|
|
88
|
+
return value(str, ...Array.from(arguments).slice(1));
|
|
89
|
+
};
|
|
90
|
+
} else if (key === 'shell') {
|
|
91
|
+
// Shell function has special handling for string arguments - it falls back to exec
|
|
92
|
+
globalThis[key] = value;
|
|
93
|
+
} else {
|
|
94
|
+
globalThis[key] = value;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Execute the JavaScript code with bunosh globals available
|
|
100
|
+
const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
|
|
101
|
+
const func = new AsyncFunction(jsCode);
|
|
102
|
+
await func();
|
|
103
|
+
return;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.error('Error executing JavaScript:', error.message);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
30
108
|
}
|
|
31
|
-
} else {
|
|
32
|
-
tasksFile = path.join(process.cwd(), BUNOSHFILE);
|
|
33
|
-
}
|
|
34
109
|
|
|
35
|
-
if (!existsSync(tasksFile)) {
|
|
36
|
-
|
|
110
|
+
if (!existsSync(tasksFile)) {
|
|
111
|
+
banner();
|
|
37
112
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
113
|
+
if (process.argv.includes('init')) {
|
|
114
|
+
init();
|
|
115
|
+
process.exit(0);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log();
|
|
119
|
+
console.error(`Bunoshfile not found: ${tasksFile}`);
|
|
120
|
+
console.log(customBunoshfile ?
|
|
121
|
+
`Run \`bunosh init\` in the directory or specify a valid --bunoshfile path` :
|
|
122
|
+
"Run `bunosh init` to create a new Bunoshfile here")
|
|
123
|
+
console.log();
|
|
124
|
+
process.exit(1);
|
|
41
125
|
}
|
|
42
126
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
127
|
+
// Import bunosh globals for normal operation
|
|
128
|
+
await import('./index.js');
|
|
129
|
+
|
|
130
|
+
import(tasksFile).then(async (tasks) => {
|
|
131
|
+
try {
|
|
132
|
+
const source = readFileSync(tasksFile, "utf-8");
|
|
133
|
+
await program(tasks, source);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
handleBunoshfileError(error, tasksFile);
|
|
136
|
+
}
|
|
137
|
+
}).catch((error) => {
|
|
138
|
+
handleBunoshfileError(error, tasksFile);
|
|
139
|
+
});
|
|
50
140
|
}
|
|
51
141
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
program(tasks, source);
|
|
56
|
-
} catch (error) {
|
|
57
|
-
handleBunoshfileError(error, tasksFile);
|
|
58
|
-
}
|
|
59
|
-
}).catch((error) => {
|
|
60
|
-
handleBunoshfileError(error, tasksFile);
|
|
142
|
+
main().catch((error) => {
|
|
143
|
+
console.error('Fatal error:', error.message);
|
|
144
|
+
process.exit(1);
|
|
61
145
|
});
|
|
62
146
|
|
|
63
147
|
// Handle unhandled promise rejections
|
|
@@ -84,9 +168,50 @@ process.on('uncaughtException', (error) => {
|
|
|
84
168
|
process.exit(1);
|
|
85
169
|
});
|
|
86
170
|
|
|
171
|
+
// Handle exit for task summary
|
|
172
|
+
process.on('exit', (code) => {
|
|
173
|
+
if (!process.env.BUNOSH_COMMAND_STARTED) return;
|
|
174
|
+
|
|
175
|
+
// Don't print summary if exit was due to stdin closing during an ask operation
|
|
176
|
+
// This prevents duplicate output when ask commands don't receive all required input
|
|
177
|
+
if (globalThis._bunoshInAskOperation && code === 0) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Access global values directly
|
|
182
|
+
const tasksExecuted = globalThis._bunoshGlobalTasksExecuted || [];
|
|
183
|
+
const TaskStatus = globalThis._bunoshGlobalTaskStatus || { FAIL: 'fail', WARNING: 'warning' };
|
|
184
|
+
|
|
185
|
+
// Calculate total time from when the process started
|
|
186
|
+
const totalTime = Date.now() - globalThis._bunoshStartTime || 0;
|
|
187
|
+
const tasksFailed = tasksExecuted.filter(ti => ti.result?.status === TaskStatus.FAIL).length;
|
|
188
|
+
const tasksWarning = tasksExecuted.filter(ti => ti.result?.status === TaskStatus.WARNING).length;
|
|
189
|
+
|
|
190
|
+
// Check if we're in test environment
|
|
191
|
+
const isTestEnvironment = process.env.NODE_ENV === 'test' ||
|
|
192
|
+
typeof Bun?.jest !== 'undefined' ||
|
|
193
|
+
process.argv.some(arg => arg.includes('vitest') || arg.includes('jest') || arg.includes('--test') || arg.includes('test:'));
|
|
194
|
+
|
|
195
|
+
// Set exit code to 1 if any tasks failed AND we're not in test environment
|
|
196
|
+
if (tasksFailed > 0 && !isTestEnvironment) {
|
|
197
|
+
process.exitCode = 1;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const finalExitCode = (tasksFailed > 0 && !isTestEnvironment) ? 1 : code;
|
|
201
|
+
const success = finalExitCode === 0;
|
|
202
|
+
|
|
203
|
+
// Debug: Check if this handler has already run
|
|
204
|
+
if (globalThis._bunoshExitHandlerCalled) {
|
|
205
|
+
console.log('\n[DEBUG] Exit handler already called, skipping duplicate');
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
globalThis._bunoshExitHandlerCalled = true;
|
|
209
|
+
|
|
210
|
+
console.log(`\n🍲 ${success ? '' : 'FAIL '}Exit Code: ${finalExitCode} | Tasks: ${tasksExecuted.length}${tasksFailed ? ` | Failed: ${tasksFailed}` : ''}${tasksWarning ? ` | Warnings: ${tasksWarning}` : ''} | Time: ${totalTime}ms`);
|
|
211
|
+
});
|
|
212
|
+
|
|
87
213
|
function handleBunoshfileError(error, filePath) {
|
|
88
|
-
banner
|
|
89
|
-
console.log();
|
|
214
|
+
// Don't show banner for errors - it interferes with error visibility
|
|
90
215
|
|
|
91
216
|
// Check for Babel parser syntax errors
|
|
92
217
|
if (error.code === 'BABEL_PARSER_SYNTAX_ERROR' ||
|
package/index.js
CHANGED
|
@@ -5,9 +5,9 @@ import writeToFile from "./src/tasks/writeToFile.js";
|
|
|
5
5
|
import copyFile from "./src/tasks/copyFile.js";
|
|
6
6
|
import ai from "./src/tasks/ai.js";
|
|
7
7
|
import { ask, yell, say } from "./src/io.js";
|
|
8
|
-
import { task, tryTask, stopOnFail, ignoreFail, stopOnFailures, ignoreFailures, silence, prints, silent } from "./src/task.js";
|
|
8
|
+
import { task, tryTask, stopOnFail, ignoreFail, stopOnFailures, ignoreFailures, silence, prints, silent, TaskResult } from "./src/task.js";
|
|
9
9
|
|
|
10
|
-
export { exec, shell, fetch, writeToFile, copyFile, ai, ask, yell, say, task, tryTask, stopOnFail, ignoreFail, stopOnFailures, ignoreFailures, silence, prints, silent };
|
|
10
|
+
export { exec, shell, fetch, writeToFile, copyFile, ai, ask, yell, say, task, tryTask, stopOnFail, ignoreFail, stopOnFailures, ignoreFailures, silence, prints, silent, TaskResult };
|
|
11
11
|
|
|
12
12
|
export function buildCmd(cmd) {
|
|
13
13
|
return function (args) {
|
|
@@ -28,12 +28,12 @@ global.bunosh = {
|
|
|
28
28
|
stopOnFail,
|
|
29
29
|
ignoreFail,
|
|
30
30
|
task,
|
|
31
|
-
try: tryTask,
|
|
32
31
|
stopOnFailures,
|
|
33
32
|
ignoreFailures,
|
|
34
33
|
silence,
|
|
35
34
|
prints,
|
|
36
35
|
silent,
|
|
36
|
+
TaskResult,
|
|
37
37
|
buildCmd,
|
|
38
38
|
$: exec,
|
|
39
39
|
};
|
package/package.json
CHANGED
package/src/init.js
CHANGED
|
@@ -4,9 +4,9 @@ import fs from 'fs';
|
|
|
4
4
|
|
|
5
5
|
const template = `
|
|
6
6
|
// Bunosh CLI required to execute tasks from this file
|
|
7
|
-
// Get it here
|
|
7
|
+
// Get it here => https://buno.sh
|
|
8
8
|
|
|
9
|
-
const { exec, fetch, writeToFile, task, ai } = global.bunosh;
|
|
9
|
+
const { exec, shell, fetch, writeToFile, task, ai } = global.bunosh;
|
|
10
10
|
|
|
11
11
|
// input/output
|
|
12
12
|
const { say, ask, yell } = global.bunosh;
|
package/src/io.js
CHANGED
|
@@ -7,6 +7,8 @@ export function say(...args) {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export async function ask(question, defaultValueOrOptions = {}, options = {}) {
|
|
10
|
+
// Track that we're in an ask operation to prevent duplicate exit summaries
|
|
11
|
+
globalThis._bunoshInAskOperation = true;
|
|
10
12
|
// Smart parameter detection
|
|
11
13
|
let opts = {};
|
|
12
14
|
|
|
@@ -37,38 +39,105 @@ export async function ask(question, defaultValueOrOptions = {}, options = {}) {
|
|
|
37
39
|
return await askWithChoices(question, opts);
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
try {
|
|
43
|
+
const answers = await inquirer.prompt({ name: question, message: question, ...opts })
|
|
44
|
+
return Object.values(answers)[0];
|
|
45
|
+
} finally {
|
|
46
|
+
// Reset ask operation flag
|
|
47
|
+
globalThis._bunoshInAskOperation = false;
|
|
48
|
+
}
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
async function askWithEditor(question, opts = {}) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
globalThis._bunoshInAskOperation = true;
|
|
53
|
+
try {
|
|
54
|
+
const answers = await inquirer.prompt({
|
|
55
|
+
name: question,
|
|
56
|
+
message: question,
|
|
57
|
+
type: 'editor',
|
|
58
|
+
...opts
|
|
59
|
+
});
|
|
60
|
+
return Object.values(answers)[0];
|
|
61
|
+
} finally {
|
|
62
|
+
globalThis._bunoshInAskOperation = false;
|
|
63
|
+
}
|
|
52
64
|
}
|
|
53
65
|
|
|
54
66
|
async function askWithChoices(question, opts = {}) {
|
|
67
|
+
globalThis._bunoshInAskOperation = true;
|
|
55
68
|
const promptType = opts.multiple ? 'checkbox' : 'list';
|
|
56
69
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
try {
|
|
71
|
+
const answers = await inquirer.prompt({
|
|
72
|
+
name: question,
|
|
73
|
+
message: question,
|
|
74
|
+
type: promptType,
|
|
75
|
+
choices: opts.choices,
|
|
76
|
+
...opts
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return Object.values(answers)[0];
|
|
80
|
+
} finally {
|
|
81
|
+
globalThis._bunoshInAskOperation = false;
|
|
82
|
+
}
|
|
66
83
|
}
|
|
67
84
|
|
|
68
85
|
export function yell(text) {
|
|
69
|
-
|
|
86
|
+
// Always use boxed capitalized format
|
|
87
|
+
const upperText = text.toUpperCase();
|
|
88
|
+
const boxText = createBoxedText(upperText);
|
|
89
|
+
console.log(boxText);
|
|
90
|
+
}
|
|
70
91
|
|
|
71
|
-
|
|
92
|
+
function createGradientAscii(asciiArt) {
|
|
93
|
+
const lines = asciiArt.split('\n');
|
|
94
|
+
const colors = [
|
|
95
|
+
chalk.bold.yellow,
|
|
96
|
+
chalk.bold.green,
|
|
97
|
+
chalk.bold.greenBright,
|
|
98
|
+
chalk.bold.cyan,
|
|
99
|
+
chalk.bold.blue
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
return lines.map((line, index) => {
|
|
103
|
+
// Create smooth gradient by interpolating between colors
|
|
104
|
+
const progress = index / (lines.length - 1);
|
|
105
|
+
const colorIndex = progress * (colors.length - 1);
|
|
106
|
+
const lowerIndex = Math.floor(colorIndex);
|
|
107
|
+
const upperIndex = Math.min(lowerIndex + 1, colors.length - 1);
|
|
108
|
+
const factor = colorIndex - lowerIndex;
|
|
109
|
+
|
|
110
|
+
// For smoother transition, we'll use the closest color
|
|
111
|
+
const color = factor < 0.5 ? colors[lowerIndex] : colors[upperIndex];
|
|
112
|
+
return color(line);
|
|
113
|
+
}).join('\n');
|
|
114
|
+
}
|
|
72
115
|
|
|
73
|
-
|
|
116
|
+
function createBoxedText(text) {
|
|
117
|
+
const maxLength = Math.max(text.length, 10);
|
|
118
|
+
const totalWidth = maxLength + 6; // 6 = 3 spaces padding on each side
|
|
119
|
+
const leftPadding = Math.floor((totalWidth - text.length) / 2);
|
|
120
|
+
const rightPadding = totalWidth - text.length - leftPadding;
|
|
121
|
+
|
|
122
|
+
// Use Unicode box drawing characters for a nice look
|
|
123
|
+
const topLeft = '╭';
|
|
124
|
+
const topRight = '╮';
|
|
125
|
+
const bottomLeft = '╰';
|
|
126
|
+
const bottomRight = '╯';
|
|
127
|
+
const horizontal = '─';
|
|
128
|
+
const vertical = '│';
|
|
129
|
+
|
|
130
|
+
const horizontalBorder = topLeft + horizontal.repeat(totalWidth) + topRight;
|
|
131
|
+
const emptyLine = vertical + ' '.repeat(totalWidth) + vertical;
|
|
132
|
+
const textLine = vertical + ' '.repeat(leftPadding) + chalk.bold(text) + ' '.repeat(rightPadding) + vertical;
|
|
133
|
+
|
|
134
|
+
return [
|
|
135
|
+
chalk.bold.cyan(horizontalBorder),
|
|
136
|
+
chalk.cyan(emptyLine),
|
|
137
|
+
chalk.cyan(emptyLine),
|
|
138
|
+
chalk.cyan(textLine),
|
|
139
|
+
chalk.cyan(emptyLine),
|
|
140
|
+
chalk.cyan(emptyLine),
|
|
141
|
+
chalk.bold.cyan(bottomLeft + horizontal.repeat(totalWidth) + bottomRight)
|
|
142
|
+
].join('\n');
|
|
74
143
|
}
|
package/src/printer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { createFormatter } from './formatters/factory.js';
|
|
3
|
-
import { getTaskPrefix } from './task.js';
|
|
3
|
+
import { getTaskPrefix, runningTasks } from './task.js';
|
|
4
4
|
|
|
5
5
|
export class Printer {
|
|
6
6
|
constructor(taskType, taskId = null) {
|
|
@@ -21,9 +21,21 @@ export class Printer {
|
|
|
21
21
|
extra.duration = Date.now() - this.startTime;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// Get task info to check for parent task
|
|
25
|
+
let displayTaskName = taskName;
|
|
26
|
+
if (this.taskId) {
|
|
27
|
+
const taskInfo = runningTasks.get(this.taskId);
|
|
28
|
+
if (taskInfo && taskInfo.parentId) {
|
|
29
|
+
const parentTask = runningTasks.get(taskInfo.parentId);
|
|
30
|
+
if (parentTask) {
|
|
31
|
+
displayTaskName = `${parentTask.name} > ${taskName}`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
24
36
|
// Add task prefix for parallel tasks
|
|
25
37
|
const prefix = this.taskId ? getTaskPrefix(this.taskId) : '';
|
|
26
|
-
const prefixedTaskName = prefix ? `${prefix} ${
|
|
38
|
+
const prefixedTaskName = prefix ? `${prefix} ${displayTaskName}` : displayTaskName;
|
|
27
39
|
|
|
28
40
|
const output = this.formatter.format(prefixedTaskName, status, this.taskType, extra);
|
|
29
41
|
if (output) {
|