neex 0.6.39 → 0.6.40
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/src/logger.js +78 -201
- package/dist/src/runner.js +5 -53
- package/dist/src/watcher.js +6 -15
- package/package.json +1 -1
package/dist/src/logger.js
CHANGED
|
@@ -3,21 +3,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
// src/logger.ts
|
|
7
6
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
7
|
const figures_1 = __importDefault(require("figures"));
|
|
9
|
-
const string_width_1 = __importDefault(require("string-width"));
|
|
10
|
-
const utils_1 = require("./utils");
|
|
11
8
|
class Logger {
|
|
9
|
+
printSummary(results) {
|
|
10
|
+
throw new Error('Method not implemented.');
|
|
11
|
+
}
|
|
12
12
|
constructor() {
|
|
13
|
-
this.prefixLength = 0;
|
|
14
13
|
this.outputBuffer = new Map();
|
|
15
14
|
this.commandColors = new Map();
|
|
16
15
|
this.startTimes = new Map();
|
|
17
|
-
this.spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
18
|
-
this.spinnerIndex = 0;
|
|
19
|
-
this.spinnerIntervals = new Map();
|
|
20
|
-
this.isSpinnerActive = false;
|
|
21
16
|
}
|
|
22
17
|
static getInstance() {
|
|
23
18
|
if (!Logger.instance) {
|
|
@@ -25,54 +20,24 @@ class Logger {
|
|
|
25
20
|
}
|
|
26
21
|
return Logger.instance;
|
|
27
22
|
}
|
|
28
|
-
getSpinnerFrame() {
|
|
29
|
-
const frame = this.spinnerFrames[this.spinnerIndex];
|
|
30
|
-
this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
|
|
31
|
-
return frame;
|
|
32
|
-
}
|
|
33
23
|
showBanner() {
|
|
34
24
|
console.log('\n' + chalk_1.default.bgHex('#0066FF').black(' Neex ') + '\n');
|
|
35
25
|
}
|
|
36
26
|
setCommands(commands) {
|
|
37
|
-
//
|
|
38
|
-
this.stopAllSpinners();
|
|
39
|
-
// Show Neex banner
|
|
40
|
-
this.showBanner();
|
|
41
|
-
// Calculate prefix length for aligning output
|
|
42
|
-
this.prefixLength = Math.max(...commands.map(cmd => (0, string_width_1.default)(cmd))) + 3;
|
|
43
|
-
// Initialize buffers and colors for each command
|
|
27
|
+
// this.showBanner(); // Banner is now called manually where needed
|
|
44
28
|
commands.forEach(cmd => {
|
|
45
29
|
this.outputBuffer.set(cmd, []);
|
|
46
|
-
this.commandColors.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
console.log(chalk_1.default.dim('» Commands to execute:'));
|
|
50
|
-
commands.forEach(cmd => {
|
|
51
|
-
const color = this.commandColors.get(cmd) || chalk_1.default.white;
|
|
52
|
-
console.log(chalk_1.default.dim(' ┌') + color(` ${cmd}`));
|
|
30
|
+
if (!this.commandColors.has(cmd)) {
|
|
31
|
+
this.commandColors.set(cmd, this.getRandomColor());
|
|
32
|
+
}
|
|
53
33
|
});
|
|
54
|
-
console.log(''); // Add a blank line after commands list
|
|
55
34
|
}
|
|
56
|
-
|
|
57
|
-
// Generate distinct colors for commands based on the command string
|
|
35
|
+
getRandomColor() {
|
|
58
36
|
const vibrantColors = [
|
|
59
|
-
'#
|
|
60
|
-
'#
|
|
61
|
-
'#FF6347',
|
|
62
|
-
'#9370DB',
|
|
63
|
-
'#FF8C00',
|
|
64
|
-
'#20B2AA',
|
|
65
|
-
'#0066FF',
|
|
66
|
-
'#4169E1',
|
|
67
|
-
'#FFD700',
|
|
68
|
-
'#8A2BE2' // Blue Violet
|
|
37
|
+
'#FF5733', '#33FF57', '#3357FF', '#FF33A1', '#A133FF',
|
|
38
|
+
'#33FFA1', '#FFC300', '#C70039', '#900C3F', '#581845'
|
|
69
39
|
];
|
|
70
|
-
|
|
71
|
-
for (let i = 0; i < command.length; i++) {
|
|
72
|
-
hash = (hash << 5) - hash + command.charCodeAt(i);
|
|
73
|
-
hash |= 0; // Convert to 32bit integer
|
|
74
|
-
}
|
|
75
|
-
const colorIndex = Math.abs(hash) % vibrantColors.length;
|
|
40
|
+
const colorIndex = Math.floor(Math.random() * vibrantColors.length);
|
|
76
41
|
return chalk_1.default.hex(vibrantColors[colorIndex]);
|
|
77
42
|
}
|
|
78
43
|
formatPrefix(command) {
|
|
@@ -84,180 +49,92 @@ class Logger {
|
|
|
84
49
|
this.outputBuffer.set(output.command, currentBuffer);
|
|
85
50
|
}
|
|
86
51
|
printBuffer(command) {
|
|
87
|
-
|
|
88
|
-
const color = this.commandColors.get(command) || chalk_1.default.white;
|
|
89
|
-
// Stop spinner for this command if running
|
|
90
|
-
this.stopSpinner(command);
|
|
91
|
-
buffer.forEach(output => {
|
|
92
|
-
const content = output.data.trim();
|
|
93
|
-
if (content) {
|
|
94
|
-
const lines = content.split('\n');
|
|
95
|
-
lines.forEach(line => {
|
|
96
|
-
if (line.trim()) {
|
|
97
|
-
const outputLine = `${line}`;
|
|
98
|
-
// Show stderr in appropriate colors
|
|
99
|
-
if (output.type === 'stderr') {
|
|
100
|
-
// Not all stderr is an error, check for warning or info patterns
|
|
101
|
-
if (line.toLowerCase().includes('warn') || line.toLowerCase().includes('warning')) {
|
|
102
|
-
console.log(`${chalk_1.default.yellow(line)}`);
|
|
103
|
-
}
|
|
104
|
-
else if (line.toLowerCase().includes('error')) {
|
|
105
|
-
console.log(`${chalk_1.default.red(line)}`);
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
console.log(`${line}`);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
console.log(outputLine);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
// Clear buffer after printing
|
|
119
|
-
this.outputBuffer.set(command, []);
|
|
52
|
+
this.flushBuffer(command);
|
|
120
53
|
}
|
|
121
54
|
clearBuffer(command) {
|
|
122
55
|
this.outputBuffer.set(command, []);
|
|
123
56
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
57
|
+
flushBuffer(command) {
|
|
58
|
+
const buffer = this.outputBuffer.get(command);
|
|
59
|
+
if (buffer) {
|
|
60
|
+
buffer.forEach(output => {
|
|
61
|
+
const prefix = this.formatPrefix(output.command);
|
|
62
|
+
const color = this.commandColors.get(output.command) || chalk_1.default.white;
|
|
63
|
+
const formattedOutput = output.data
|
|
64
|
+
.split('\n')
|
|
65
|
+
.filter(line => line.trim() !== '')
|
|
66
|
+
.map(line => `${prefix}${color(line)}`)
|
|
67
|
+
.join('\n');
|
|
68
|
+
if (formattedOutput) {
|
|
69
|
+
if (output.type === 'stderr') {
|
|
70
|
+
console.error(formattedOutput);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
console.log(formattedOutput);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
this.outputBuffer.set(command, []);
|
|
133
78
|
}
|
|
134
79
|
}
|
|
80
|
+
printLine(message, level = 'info') {
|
|
81
|
+
// This is intentionally left blank to suppress verbose logs
|
|
82
|
+
}
|
|
83
|
+
printEnd(result, minimalOutput) {
|
|
84
|
+
this.printExit(result.command, result.code);
|
|
85
|
+
}
|
|
135
86
|
printStart(command) {
|
|
136
|
-
// Record start time
|
|
137
87
|
this.startTimes.set(command, new Date());
|
|
138
88
|
const color = this.commandColors.get(command) || chalk_1.default.white;
|
|
139
|
-
// Stop any previous spinner for this command (e.g. if retrying)
|
|
140
|
-
this.stopSpinner(command);
|
|
141
|
-
// Clear the line before printing "Starting..."
|
|
142
|
-
if (this.isSpinnerActive) { // Check if any spinner was active to avoid clearing unnecessarily
|
|
143
|
-
process.stdout.write('\r' + ' '.repeat(process.stdout.columns || 80) + '\r');
|
|
144
|
-
}
|
|
145
89
|
console.log(`${color('Starting...')}`);
|
|
146
|
-
// Start spinner for this command
|
|
147
|
-
this.startSpinner(command);
|
|
148
|
-
}
|
|
149
|
-
startSpinner(command) {
|
|
150
|
-
// Only create a spinner if one doesn't already exist for this command
|
|
151
|
-
if (this.spinnerIntervals.has(command)) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
this.isSpinnerActive = true;
|
|
155
|
-
const color = this.commandColors.get(command) || chalk_1.default.white;
|
|
156
|
-
const interval = setInterval(() => {
|
|
157
|
-
const frame = this.getSpinnerFrame();
|
|
158
|
-
process.stdout.write(`\r${color(frame)} ${chalk_1.default.dim('Running...')}`);
|
|
159
|
-
}, 80);
|
|
160
|
-
this.spinnerIntervals.set(command, interval);
|
|
161
|
-
}
|
|
162
|
-
stopSpinner(command) {
|
|
163
|
-
const interval = this.spinnerIntervals.get(command);
|
|
164
|
-
if (interval) {
|
|
165
|
-
clearInterval(interval);
|
|
166
|
-
this.spinnerIntervals.delete(command);
|
|
167
|
-
// Clear the spinner line
|
|
168
|
-
if (this.isSpinnerActive) {
|
|
169
|
-
process.stdout.write('\r' + ' '.repeat(process.stdout.columns || 80) + '\r');
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
stopAllSpinners() {
|
|
174
|
-
this.spinnerIntervals.forEach((interval, command) => {
|
|
175
|
-
clearInterval(interval);
|
|
176
|
-
});
|
|
177
|
-
this.spinnerIntervals.clear();
|
|
178
|
-
this.isSpinnerActive = false;
|
|
179
|
-
// Clear the spinner line if any spinner was active
|
|
180
|
-
if (this.isSpinnerActive) {
|
|
181
|
-
process.stdout.write('\r' + ' '.repeat(process.stdout.columns || 80) + '\r');
|
|
182
|
-
}
|
|
183
90
|
}
|
|
184
91
|
printSuccess(result) {
|
|
185
92
|
const { command, duration } = result;
|
|
186
|
-
this.
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
? ` ${chalk_1.default.dim(`(${(duration / 1000).toFixed(2)}s)`)}`
|
|
190
|
-
: '';
|
|
191
|
-
console.log(`${chalk_1.default.green(figures_1.default.tick)} ${chalk_1.default.green('Completed')}${durationStr}`);
|
|
93
|
+
const color = this.commandColors.get(command) || chalk_1.default.green;
|
|
94
|
+
const prefix = this.formatPrefix(command);
|
|
95
|
+
console.log(color(`${prefix}${figures_1.default.tick} Success! (${duration.toFixed(2)}ms)`));
|
|
192
96
|
}
|
|
193
97
|
printError(result) {
|
|
194
|
-
const { command,
|
|
195
|
-
this.
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (result.duration !== null) {
|
|
207
|
-
// Ensure result.duration is treated as a number here
|
|
208
|
-
durationDisplay = `(${(0, utils_1.formatDuration)(result.duration)})`;
|
|
209
|
-
}
|
|
210
|
-
const duration = durationDisplay;
|
|
211
|
-
if (minimalOutput) {
|
|
212
|
-
if (!result.success) {
|
|
213
|
-
const status = result.code !== null ? `failed (code ${result.code})` : 'failed';
|
|
214
|
-
this.printLine(`${chalk_1.default.red(figures_1.default.cross)} ${result.command} ${status} ${duration}`, 'error');
|
|
215
|
-
}
|
|
98
|
+
const { command, duration, code } = result;
|
|
99
|
+
const color = this.commandColors.get(command) || chalk_1.default.red;
|
|
100
|
+
const prefix = this.formatPrefix(command);
|
|
101
|
+
console.error(color(`${prefix}${figures_1.default.cross} Failed with exit code ${code} (${duration.toFixed(2)}ms)`));
|
|
102
|
+
}
|
|
103
|
+
printExit(command, code) {
|
|
104
|
+
const startTime = this.startTimes.get(command);
|
|
105
|
+
const duration = startTime ? new Date().getTime() - startTime.getTime() : 0;
|
|
106
|
+
const result = { command, code: code !== null && code !== void 0 ? code : 1, duration };
|
|
107
|
+
this.flushBuffer(command);
|
|
108
|
+
if (code === 0) {
|
|
109
|
+
this.printSuccess(result);
|
|
216
110
|
}
|
|
217
111
|
else {
|
|
218
|
-
|
|
219
|
-
this.printLine(`${chalk_1.default.green(figures_1.default.tick)} Command "${result.command}" finished successfully ${duration}`, 'info');
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
const errorCode = result.code !== null ? ` (code ${result.code})` : '';
|
|
223
|
-
const errorMessage = result.error ? `: ${result.error.message}` : '';
|
|
224
|
-
this.printLine(`${chalk_1.default.red(figures_1.default.cross)} Command "${result.command}" failed${errorCode}${errorMessage} ${duration}`, 'error');
|
|
225
|
-
}
|
|
112
|
+
this.printError(result);
|
|
226
113
|
}
|
|
227
114
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
.filter(
|
|
242
|
-
.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
console.log('\n' + chalk_1.default.red.bold('Failed commands:'));
|
|
252
|
-
results
|
|
253
|
-
.filter(r => !r.success)
|
|
254
|
-
.forEach(result => {
|
|
255
|
-
const color = this.commandColors.get(result.command) || chalk_1.default.white;
|
|
256
|
-
const duration = result.duration
|
|
257
|
-
? chalk_1.default.dim(` (${(result.duration / 1000).toFixed(2)}s)`)
|
|
258
|
-
: '';
|
|
259
|
-
const code = result.code !== null ? chalk_1.default.red(` [code: ${result.code}]`) : '';
|
|
260
|
-
console.log(` ${chalk_1.default.red(figures_1.default.cross)} ${color(result.command)}${code}${duration}`);
|
|
115
|
+
printBulkOutput(outputs) {
|
|
116
|
+
if (outputs.length > 0) {
|
|
117
|
+
outputs
|
|
118
|
+
.map(output => {
|
|
119
|
+
const color = this.commandColors.get(output.command) || chalk_1.default.white;
|
|
120
|
+
const prefix = this.formatPrefix(output.command);
|
|
121
|
+
return {
|
|
122
|
+
...output,
|
|
123
|
+
prefix,
|
|
124
|
+
color
|
|
125
|
+
};
|
|
126
|
+
})
|
|
127
|
+
.forEach(({ command, type, data, prefix, color }) => {
|
|
128
|
+
const lines = data.split('\n').filter(line => line.trim() !== '');
|
|
129
|
+
if (lines.length > 0) {
|
|
130
|
+
const formatted = lines.map(line => `${prefix}${color(line)}`).join('\n');
|
|
131
|
+
if (type === 'stderr') {
|
|
132
|
+
console.error(formatted);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
console.log(formatted);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
261
138
|
});
|
|
262
139
|
}
|
|
263
140
|
}
|
package/dist/src/runner.js
CHANGED
|
@@ -27,11 +27,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
exports.Runner = void 0;
|
|
30
|
-
// src/runner.ts - Updated version
|
|
31
30
|
const child_process_1 = require("child_process");
|
|
32
31
|
const fsPromises = __importStar(require("fs/promises"));
|
|
33
32
|
const path = __importStar(require("path"));
|
|
34
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
35
33
|
const logger_1 = __importDefault(require("./logger"));
|
|
36
34
|
const p_map_1 = __importDefault(require("p-map"));
|
|
37
35
|
const npm_run_path_1 = __importDefault(require("npm-run-path"));
|
|
@@ -56,7 +54,6 @@ class Runner {
|
|
|
56
54
|
}
|
|
57
55
|
}
|
|
58
56
|
catch (error) {
|
|
59
|
-
logger_1.default.printLine(`Could not read or parse package.json: ${error.message}`, 'warn');
|
|
60
57
|
packageJson = { scripts: {} };
|
|
61
58
|
}
|
|
62
59
|
for (const command of commands) {
|
|
@@ -65,13 +62,12 @@ class Runner {
|
|
|
65
62
|
let foundMatch = false;
|
|
66
63
|
for (const scriptName in packageJson.scripts) {
|
|
67
64
|
if (pattern.test(scriptName)) {
|
|
68
|
-
expandedCommands.push(scriptName);
|
|
65
|
+
expandedCommands.push(scriptName);
|
|
69
66
|
foundMatch = true;
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
69
|
if (!foundMatch) {
|
|
73
|
-
|
|
74
|
-
expandedCommands.push(command); // Add original command if no match
|
|
70
|
+
expandedCommands.push(command);
|
|
75
71
|
}
|
|
76
72
|
}
|
|
77
73
|
else {
|
|
@@ -95,21 +91,18 @@ class Runner {
|
|
|
95
91
|
return { executableCommand: commandToExecute, executionCwd: targetCwd };
|
|
96
92
|
}
|
|
97
93
|
else {
|
|
98
|
-
// It's a script from package.json, but no 'cd ... && ...' pattern
|
|
99
94
|
return { executableCommand: scriptValue, executionCwd: baseDir };
|
|
100
95
|
}
|
|
101
96
|
}
|
|
102
97
|
}
|
|
103
98
|
catch (error) {
|
|
104
|
-
// Errors
|
|
105
|
-
// Will treat as direct command
|
|
99
|
+
// Errors will treat as direct command
|
|
106
100
|
}
|
|
107
101
|
return { executableCommand: scriptNameOrCommand, executionCwd: undefined };
|
|
108
102
|
}
|
|
109
103
|
detectServerInfo(command, data) {
|
|
110
104
|
if (!this.options.isServerMode)
|
|
111
105
|
return;
|
|
112
|
-
// Get or create server info
|
|
113
106
|
let serverInfo = this.serverInfo.get(command);
|
|
114
107
|
if (!serverInfo) {
|
|
115
108
|
serverInfo = {
|
|
@@ -118,25 +111,16 @@ class Runner {
|
|
|
118
111
|
};
|
|
119
112
|
this.serverInfo.set(command, serverInfo);
|
|
120
113
|
}
|
|
121
|
-
// Try to detect port from output
|
|
122
114
|
const portMatch = data.match(this.portRegex);
|
|
123
115
|
if (portMatch && portMatch[1]) {
|
|
124
116
|
serverInfo.port = parseInt(portMatch[1], 10);
|
|
125
117
|
serverInfo.status = 'running';
|
|
126
|
-
// Only log if we just discovered the port
|
|
127
|
-
if (!serverInfo.url) {
|
|
128
|
-
logger_1.default.printLine(`Server ${command} running on port ${serverInfo.port}`, 'info');
|
|
129
|
-
}
|
|
130
118
|
}
|
|
131
|
-
// Try to detect full URL from output
|
|
132
119
|
const urlMatch = data.match(this.urlRegex);
|
|
133
120
|
if (urlMatch && urlMatch[1]) {
|
|
134
121
|
serverInfo.url = urlMatch[1];
|
|
135
122
|
serverInfo.status = 'running';
|
|
136
|
-
// Log the full URL once we detect it
|
|
137
|
-
logger_1.default.printLine(`Server ${command} available at ${chalk_1.default.cyan(serverInfo.url)}`, 'info');
|
|
138
123
|
}
|
|
139
|
-
// Update server info
|
|
140
124
|
this.serverInfo.set(command, serverInfo);
|
|
141
125
|
}
|
|
142
126
|
async runCommand(originalCommand, currentRetry = 0) {
|
|
@@ -148,6 +132,7 @@ class Runner {
|
|
|
148
132
|
code: null,
|
|
149
133
|
startTime,
|
|
150
134
|
endTime: null,
|
|
135
|
+
duration: 0,
|
|
151
136
|
output: [],
|
|
152
137
|
stderr: []
|
|
153
138
|
};
|
|
@@ -218,13 +203,11 @@ class Runner {
|
|
|
218
203
|
serverInfo.status = 'error';
|
|
219
204
|
this.serverInfo.set(originalCommand, serverInfo);
|
|
220
205
|
}
|
|
221
|
-
logger_1.default.printLine(`Command "${originalCommand}" failed to start: ${err.message}`, 'error');
|
|
222
206
|
}
|
|
223
207
|
logger_1.default.printBuffer(originalCommand);
|
|
224
208
|
if (this.options.printOutput)
|
|
225
209
|
logger_1.default.printEnd(result, this.options.minimalOutput);
|
|
226
210
|
if (this.options.retry && this.options.retry > 0 && currentRetry < this.options.retry) {
|
|
227
|
-
logger_1.default.printLine(`Command "${originalCommand}" failed with error. Retrying (${currentRetry + 1}/${this.options.retry})...`, 'warn');
|
|
228
211
|
if (this.options.retryDelay && this.options.retryDelay > 0) {
|
|
229
212
|
await new Promise(res => setTimeout(res, this.options.retryDelay));
|
|
230
213
|
}
|
|
@@ -240,22 +223,17 @@ class Runner {
|
|
|
240
223
|
result.success = code === 0;
|
|
241
224
|
result.endTime = new Date();
|
|
242
225
|
result.duration = result.endTime.getTime() - startTime.getTime();
|
|
243
|
-
this.activeProcesses.delete(originalCommand);
|
|
244
226
|
if (this.options.isServerMode) {
|
|
245
227
|
const serverInfo = this.serverInfo.get(originalCommand);
|
|
246
228
|
if (serverInfo) {
|
|
247
229
|
serverInfo.status = code === 0 ? 'stopped' : 'error';
|
|
248
230
|
this.serverInfo.set(originalCommand, serverInfo);
|
|
249
231
|
}
|
|
250
|
-
if (code !== 0) {
|
|
251
|
-
logger_1.default.printLine(`Server "${originalCommand}" exited with code ${code}`, 'error');
|
|
252
|
-
}
|
|
253
232
|
}
|
|
254
233
|
logger_1.default.printBuffer(originalCommand);
|
|
255
234
|
if (this.options.printOutput)
|
|
256
235
|
logger_1.default.printEnd(result, this.options.minimalOutput);
|
|
257
236
|
if (!result.success && this.options.retry && this.options.retry > 0 && currentRetry < this.options.retry) {
|
|
258
|
-
logger_1.default.printLine(`Command "${originalCommand}" failed with code ${code}. Retrying (${currentRetry + 1}/${this.options.retry})...`, 'warn');
|
|
259
237
|
if (this.options.retryDelay && this.options.retryDelay > 0) {
|
|
260
238
|
await new Promise(res => setTimeout(res, this.options.retryDelay));
|
|
261
239
|
}
|
|
@@ -291,65 +269,39 @@ class Runner {
|
|
|
291
269
|
});
|
|
292
270
|
}
|
|
293
271
|
catch (error) {
|
|
294
|
-
if (this.options.isServerMode) {
|
|
295
|
-
logger_1.default.printLine('One or more servers failed to start. Stopping all servers.', 'error');
|
|
296
|
-
}
|
|
297
272
|
return [];
|
|
298
273
|
}
|
|
299
274
|
}
|
|
300
275
|
async run(initialCommands) {
|
|
301
276
|
const commands = await this.expandWildcardCommands(initialCommands);
|
|
302
277
|
if (commands.length === 0) {
|
|
303
|
-
logger_1.default.printLine('No commands to run after wildcard expansion.', 'warn');
|
|
304
278
|
return [];
|
|
305
279
|
}
|
|
306
|
-
// Initialize logger with the final list of commands
|
|
307
280
|
logger_1.default.setCommands(commands);
|
|
308
|
-
// Run in parallel or sequential mode
|
|
309
281
|
if (this.options.parallel) {
|
|
310
|
-
if (this.options.isServerMode) {
|
|
311
|
-
logger_1.default.printLine('Starting servers in parallel mode', 'info');
|
|
312
|
-
}
|
|
313
282
|
return this.runParallel(commands);
|
|
314
283
|
}
|
|
315
284
|
else {
|
|
316
|
-
if (this.options.isServerMode) {
|
|
317
|
-
logger_1.default.printLine('Starting servers in sequential mode', 'info');
|
|
318
|
-
}
|
|
319
285
|
return this.runSequential(commands);
|
|
320
286
|
}
|
|
321
287
|
}
|
|
322
288
|
cleanup(signal = 'SIGTERM') {
|
|
323
|
-
logger_1.default.printLine('Cleaning up child processes...', 'warn');
|
|
324
289
|
this.activeProcesses.forEach((proc, command) => {
|
|
325
290
|
if (proc.pid && !proc.killed) {
|
|
326
291
|
try {
|
|
327
|
-
// Kill process group
|
|
328
292
|
process.kill(-proc.pid, signal);
|
|
329
|
-
logger_1.default.printLine(`Sent ${signal} to process group ${proc.pid} (${command})`, 'info');
|
|
330
293
|
}
|
|
331
294
|
catch (e) {
|
|
332
|
-
// Fallback if killing group failed
|
|
333
295
|
try {
|
|
334
296
|
proc.kill(signal);
|
|
335
|
-
logger_1.default.printLine(`Sent ${signal} to process ${proc.pid} (${command})`, 'info');
|
|
336
297
|
}
|
|
337
298
|
catch (errInner) {
|
|
338
|
-
|
|
299
|
+
// Failed to kill
|
|
339
300
|
}
|
|
340
301
|
}
|
|
341
302
|
}
|
|
342
303
|
});
|
|
343
304
|
this.activeProcesses.clear();
|
|
344
|
-
// Print server status summary if in server mode
|
|
345
|
-
if (this.options.isServerMode && this.serverInfo.size > 0) {
|
|
346
|
-
logger_1.default.printLine('Server shutdown summary:', 'info');
|
|
347
|
-
this.serverInfo.forEach((info, command) => {
|
|
348
|
-
const statusColor = info.status === 'running' ? chalk_1.default.green :
|
|
349
|
-
info.status === 'error' ? chalk_1.default.red : chalk_1.default.yellow;
|
|
350
|
-
logger_1.default.printLine(` ${command}: ${statusColor(info.status)}`, 'info');
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
305
|
}
|
|
354
306
|
}
|
|
355
307
|
exports.Runner = Runner;
|
package/dist/src/watcher.js
CHANGED
|
@@ -22,17 +22,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
26
|
exports.FileWatcher = void 0;
|
|
30
27
|
// src/watcher.ts - File watcher for development (nodemon functionality)
|
|
31
28
|
const fs = __importStar(require("fs"));
|
|
32
29
|
const path = __importStar(require("path"));
|
|
33
30
|
const events_1 = require("events");
|
|
34
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
35
|
-
const logger_1 = __importDefault(require("./logger"));
|
|
36
31
|
class FileWatcher extends events_1.EventEmitter {
|
|
37
32
|
constructor(options) {
|
|
38
33
|
super();
|
|
@@ -121,7 +116,7 @@ class FileWatcher extends events_1.EventEmitter {
|
|
|
121
116
|
try {
|
|
122
117
|
const absolutePath = path.resolve(dirPath);
|
|
123
118
|
if (this.options.verbose) {
|
|
124
|
-
|
|
119
|
+
// logger.printLine(`Watching directory: ${chalk.cyan(absolutePath)}`, 'info');
|
|
125
120
|
}
|
|
126
121
|
const watcher = fs.watch(absolutePath, { recursive: true }, async (eventType, filename) => {
|
|
127
122
|
if (!filename)
|
|
@@ -139,7 +134,7 @@ class FileWatcher extends events_1.EventEmitter {
|
|
|
139
134
|
}
|
|
140
135
|
catch (error) {
|
|
141
136
|
if (this.options.verbose) {
|
|
142
|
-
|
|
137
|
+
// logger.printLine(`Failed to watch directory ${dirPath}: ${(error as Error).message}`, 'warn');
|
|
143
138
|
}
|
|
144
139
|
}
|
|
145
140
|
}
|
|
@@ -153,7 +148,7 @@ class FileWatcher extends events_1.EventEmitter {
|
|
|
153
148
|
return;
|
|
154
149
|
}
|
|
155
150
|
if (this.options.verbose) {
|
|
156
|
-
|
|
151
|
+
// logger.printLine(`Watching file: ${chalk.cyan(absolutePath)}`, 'info');
|
|
157
152
|
}
|
|
158
153
|
const watcher = fs.watch(absolutePath, (eventType) => {
|
|
159
154
|
this.handleFileChange(absolutePath, eventType);
|
|
@@ -163,13 +158,13 @@ class FileWatcher extends events_1.EventEmitter {
|
|
|
163
158
|
}
|
|
164
159
|
catch (error) {
|
|
165
160
|
if (this.options.verbose) {
|
|
166
|
-
|
|
161
|
+
// logger.printLine(`Failed to watch file ${filePath}: ${(error as Error).message}`, 'warn');
|
|
167
162
|
}
|
|
168
163
|
}
|
|
169
164
|
}
|
|
170
165
|
handleFileChange(filePath, eventType) {
|
|
171
166
|
if (this.options.verbose) {
|
|
172
|
-
|
|
167
|
+
// logger.printLine(`File ${eventType}: ${chalk.yellow(path.relative(process.cwd(), filePath))}`, 'info');
|
|
173
168
|
}
|
|
174
169
|
// Debounce file changes
|
|
175
170
|
if (this.debounceTimer) {
|
|
@@ -200,20 +195,17 @@ class FileWatcher extends events_1.EventEmitter {
|
|
|
200
195
|
}
|
|
201
196
|
}
|
|
202
197
|
catch (error) {
|
|
203
|
-
|
|
198
|
+
// logger.printLine(`Cannot watch ${watchPath}: ${(error as Error).message}`, 'warn');
|
|
204
199
|
}
|
|
205
200
|
}
|
|
206
201
|
const watchedCount = this.watchers.length;
|
|
207
|
-
logger_1.default.printLine(`File watcher started. Monitoring ${chalk_1.default.green(watchedCount)} locations`, 'info');
|
|
208
202
|
if (this.options.ext && this.options.ext.length > 0) {
|
|
209
|
-
logger_1.default.printLine(`Watching extensions: ${chalk_1.default.cyan(this.options.ext.join(', '))}`, 'info');
|
|
210
203
|
}
|
|
211
204
|
}
|
|
212
205
|
stop() {
|
|
213
206
|
if (!this.isWatching) {
|
|
214
207
|
return;
|
|
215
208
|
}
|
|
216
|
-
logger_1.default.printLine('Stopping file watcher...', 'info');
|
|
217
209
|
this.watchers.forEach(watcher => {
|
|
218
210
|
try {
|
|
219
211
|
watcher.close();
|
|
@@ -229,7 +221,6 @@ class FileWatcher extends events_1.EventEmitter {
|
|
|
229
221
|
clearTimeout(this.debounceTimer);
|
|
230
222
|
this.debounceTimer = null;
|
|
231
223
|
}
|
|
232
|
-
logger_1.default.printLine('File watcher stopped', 'info');
|
|
233
224
|
}
|
|
234
225
|
isActive() {
|
|
235
226
|
return this.isWatching;
|