neex 0.6.38 → 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.
@@ -32,31 +32,6 @@ const chalk_1 = __importDefault(require("chalk"));
32
32
  const figures_1 = __importDefault(require("figures"));
33
33
  const path = __importStar(require("path"));
34
34
  const fs = __importStar(require("fs/promises"));
35
- // Simple logger class - no spinners, no complex features
36
- class SimpleLogger {
37
- info(message) {
38
- console.log(chalk_1.default.blue(`${figures_1.default.info} ${message}`));
39
- }
40
- success(message) {
41
- console.log(chalk_1.default.green(`${figures_1.default.tick} ${message}`));
42
- }
43
- warning(message) {
44
- console.log(chalk_1.default.yellow(`${figures_1.default.warning} ${message}`));
45
- }
46
- error(message) {
47
- console.log(chalk_1.default.red(`${figures_1.default.cross} ${message}`));
48
- }
49
- gray(message) {
50
- console.log(chalk_1.default.gray(message));
51
- }
52
- cyan(message) {
53
- console.log(chalk_1.default.cyan(message));
54
- }
55
- log(message) {
56
- console.log(message);
57
- }
58
- }
59
- const logger = new SimpleLogger();
60
35
  // Helper function to check if file exists
61
36
  async function fileExists(filePath) {
62
37
  try {
@@ -76,26 +51,26 @@ async function getBestCommand(filePath, showInfo) {
76
51
  throw new Error(`File not found: ${filePath}`);
77
52
  }
78
53
  if (showInfo) {
79
- logger.info(`neex dev: Analyzing ${chalk_1.default.cyan(path.basename(filePath))}`);
54
+ console.log(chalk_1.default.blue(`${figures_1.default.info} neex dev: Analyzing ${chalk_1.default.cyan(path.basename(filePath))}`));
80
55
  }
81
56
  switch (ext) {
82
57
  case '.ts':
83
58
  case '.mts':
84
59
  case '.cts':
85
60
  if (showInfo) {
86
- logger.success(`neex dev: TypeScript detected, ready to run`);
61
+ console.log(chalk_1.default.green(`${figures_1.default.tick} neex dev: TypeScript detected, ready to run`));
87
62
  }
88
63
  return `npx ts-node ${filePath}`;
89
64
  case '.js':
90
65
  case '.mjs':
91
66
  case '.cjs':
92
67
  if (showInfo) {
93
- logger.success(`neex dev: JavaScript detected, ready to run`);
68
+ console.log(chalk_1.default.green(`${figures_1.default.tick} neex dev: JavaScript detected, ready to run`));
94
69
  }
95
70
  return `node ${filePath}`;
96
71
  default:
97
72
  if (showInfo) {
98
- logger.warning(`neex dev: Unknown file type, using Node.js`);
73
+ console.log(chalk_1.default.yellow(`${figures_1.default.warning} neex dev: Unknown file type, using Node.js`));
99
74
  }
100
75
  return `node ${filePath}`;
101
76
  }
@@ -125,14 +100,14 @@ function addDevCommands(program) {
125
100
  try {
126
101
  const showInfo = options.info || false;
127
102
  if (showInfo) {
128
- logger.info(`neex dev: Starting enhanced development server...`);
129
- logger.info(`neex dev: Target file: ${chalk_1.default.cyan(file)}`);
103
+ console.log(chalk_1.default.blue(`${figures_1.default.info} neex dev: Starting enhanced development server...`));
104
+ console.log(chalk_1.default.blue(`${figures_1.default.info} neex dev: Target file: ${chalk_1.default.cyan(file)}`));
130
105
  }
131
106
  // Validate file parameter
132
107
  if (!file || file.trim() === '') {
133
- logger.error(`neex dev: Error - No file specified!`);
134
- logger.log(chalk_1.default.yellow(`${figures_1.default.pointer} Usage: neex dev <file>`));
135
- logger.log(chalk_1.default.yellow(`${figures_1.default.pointer} Example: neex dev src/server.ts`));
108
+ console.error(chalk_1.default.red(`${figures_1.default.cross} neex dev: Error - No file specified!`));
109
+ console.error(chalk_1.default.yellow(`${figures_1.default.pointer} Usage: neex dev <file>`));
110
+ console.error(chalk_1.default.yellow(`${figures_1.default.pointer} Example: neex dev src/server.ts`));
136
111
  process.exit(1);
137
112
  }
138
113
  // Get the best command to run the file
@@ -143,7 +118,7 @@ function addDevCommands(program) {
143
118
  fileExtension = path.extname(file).toLowerCase();
144
119
  }
145
120
  catch (error) {
146
- logger.error(`neex dev: ${error instanceof Error ? error.message : 'Unknown error occurred'}`);
121
+ console.error(chalk_1.default.red(`${figures_1.default.cross} neex dev: ${error instanceof Error ? error.message : 'Unknown error occurred'}`));
147
122
  process.exit(1);
148
123
  }
149
124
  // Setup watch configuration
@@ -164,20 +139,20 @@ function addDevCommands(program) {
164
139
  const extensions = options.ext || ['js', 'mjs', 'json', 'ts', 'tsx', 'jsx', 'vue', 'svelte'];
165
140
  // Log configuration only if --info flag is set
166
141
  if (showInfo) {
167
- logger.info(`neex dev: Configuration:`);
168
- logger.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Target: ${chalk_1.default.cyan(file)}`));
169
- logger.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Runtime: ${chalk_1.default.cyan(fileExtension === '.ts' || fileExtension === '.mts' || fileExtension === '.cts' ? 'TypeScript' : 'JavaScript')}`));
170
- logger.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Watch paths: ${chalk_1.default.cyan(watchPaths.join(', '))}`));
171
- logger.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Extensions: ${chalk_1.default.cyan(extensions.join(', '))}`));
172
- logger.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Restart delay: ${chalk_1.default.cyan(options.delay || 1000)}ms`));
173
- logger.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Clear console: ${chalk_1.default.cyan(options.clear ? 'Yes' : 'No')}`));
142
+ console.log(chalk_1.default.blue(`${figures_1.default.info} neex dev: Configuration:`));
143
+ console.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Target: ${chalk_1.default.cyan(file)}`));
144
+ console.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Runtime: ${chalk_1.default.cyan(fileExtension === '.ts' || fileExtension === '.mts' || fileExtension === '.cts' ? 'TypeScript' : 'JavaScript')}`));
145
+ console.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Watch paths: ${chalk_1.default.cyan(watchPaths.join(', '))}`));
146
+ console.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Extensions: ${chalk_1.default.cyan(extensions.join(', '))}`));
147
+ console.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Restart delay: ${chalk_1.default.cyan(options.delay || 1000)}ms`));
148
+ console.log(chalk_1.default.blue(` ${figures_1.default.arrowRight} Clear console: ${chalk_1.default.cyan(options.clear ? 'Yes' : 'No')}`));
174
149
  if (options.verbose) {
175
- logger.info(`neex dev: Verbose mode enabled - showing detailed logs`);
150
+ console.log(chalk_1.default.blue(`${figures_1.default.info} neex dev: Verbose mode enabled - showing detailed logs`));
176
151
  }
177
- logger.success(`neex dev: Starting file watcher and process manager...`);
178
- logger.success(`neex dev: Launching ${chalk_1.default.cyan(path.basename(file))} with auto-restart capability...`);
179
- logger.info(`neex dev: Press Ctrl+C to stop the development server`);
180
- logger.gray(`${'='.repeat(60)}`);
152
+ console.log(chalk_1.default.green(`${figures_1.default.tick} neex dev: Starting file watcher and process manager...`));
153
+ console.log(chalk_1.default.green(`${figures_1.default.tick} neex dev: Launching ${chalk_1.default.cyan(path.basename(file))} with auto-restart capability...`));
154
+ console.log(chalk_1.default.blue(`${figures_1.default.info} neex dev: Press Ctrl+C to stop the development server`));
155
+ console.log(chalk_1.default.gray(`${'='.repeat(60)}`));
181
156
  }
182
157
  // Create DevRunner instance
183
158
  devRunner = new dev_runner_js_1.DevRunner({
@@ -205,17 +180,17 @@ function addDevCommands(program) {
205
180
  await devRunner.start([commandToExecute]);
206
181
  }
207
182
  catch (error) {
208
- logger.error(`neex dev: Fatal error occurred`);
183
+ console.error(chalk_1.default.red(`${figures_1.default.cross} neex dev: Fatal error occurred`));
209
184
  if (error instanceof Error) {
210
- logger.error(`Details: ${error.message}`);
185
+ console.error(chalk_1.default.red(`${figures_1.default.cross} Details: ${error.message}`));
211
186
  if (options.verbose && error.stack) {
212
- logger.gray(`Stack trace:\n${error.stack}`);
187
+ console.error(chalk_1.default.gray(`Stack trace:\n${error.stack}`));
213
188
  }
214
189
  }
215
190
  else {
216
- logger.error(`Unknown error occurred`);
191
+ console.error(chalk_1.default.red(`${figures_1.default.cross} Unknown error occurred`));
217
192
  }
218
- logger.log(chalk_1.default.yellow(`${figures_1.default.pointer} Try running with --verbose flag for more details`));
193
+ console.error(chalk_1.default.yellow(`${figures_1.default.pointer} Try running with --verbose flag for more details`));
219
194
  process.exit(1);
220
195
  }
221
196
  });
@@ -224,9 +199,9 @@ function addDevCommands(program) {
224
199
  getDevRunner: () => devRunner,
225
200
  cleanupDev: () => {
226
201
  if (devRunner && devRunner.isActive()) {
227
- logger.info(`neex dev: Stopping development server...`);
202
+ console.log(chalk_1.default.blue(`${figures_1.default.info} neex dev: Stopping development server...`));
228
203
  devRunner.stop();
229
- logger.success(`neex dev: Development server stopped successfully`);
204
+ console.log(chalk_1.default.green(`${figures_1.default.tick} neex dev: Development server stopped successfully`));
230
205
  }
231
206
  }
232
207
  };
@@ -9,31 +9,7 @@ const watcher_1 = require("./watcher");
9
9
  const runner_1 = require("./runner");
10
10
  const chalk_1 = __importDefault(require("chalk"));
11
11
  const figures_1 = __importDefault(require("figures"));
12
- // Simple logger class - no spinners, no complex features
13
- class SimpleLogger {
14
- info(message) {
15
- console.log(chalk_1.default.blue(`${figures_1.default.info} ${message}`));
16
- }
17
- success(message) {
18
- console.log(chalk_1.default.green(`${figures_1.default.tick} ${message}`));
19
- }
20
- warning(message) {
21
- console.log(chalk_1.default.yellow(`${figures_1.default.warning} ${message}`));
22
- }
23
- error(message) {
24
- console.log(chalk_1.default.red(`${figures_1.default.cross} ${message}`));
25
- }
26
- gray(message) {
27
- console.log(chalk_1.default.gray(message));
28
- }
29
- cyan(message) {
30
- console.log(chalk_1.default.cyan(message));
31
- }
32
- log(message) {
33
- console.log(message);
34
- }
35
- }
36
- const logger = new SimpleLogger();
12
+ const logger_1 = __importDefault(require("./logger"));
37
13
  class DevRunner {
38
14
  constructor(options) {
39
15
  this.commands = [];
@@ -92,10 +68,6 @@ class DevRunner {
92
68
  });
93
69
  }
94
70
  async handleFileChange(event) {
95
- const prefix = chalk_1.default.cyan(`[${this.options.runnerName}]`);
96
- if (this.options.showInfo) {
97
- logger.log(`${prefix} File changed: ${chalk_1.default.yellow(event.relativePath)}`);
98
- }
99
71
  if (this.options.clearConsole) {
100
72
  console.clear();
101
73
  }
@@ -126,9 +98,6 @@ class DevRunner {
126
98
  return results;
127
99
  }
128
100
  catch (error) {
129
- if (this.options.showInfo) {
130
- logger.error(`Execution failed: ${error.message}`);
131
- }
132
101
  return [];
133
102
  }
134
103
  }
@@ -179,16 +148,12 @@ class DevRunner {
179
148
  await this.fileWatcher.start();
180
149
  }
181
150
  // Run initial commands
182
- const prefix = chalk_1.default.cyan(`[${this.options.runnerName}]`);
183
- if (this.options.showInfo) {
184
- logger.log(`${prefix} Starting development server...`);
185
- }
186
151
  await this.runCommands();
187
152
  // Set up graceful shutdown
188
153
  this.setupGracefulShutdown();
189
154
  if (this.options.showInfo) {
190
- logger.log(`${prefix} Development server started. Watching for changes...`);
191
- logger.log(`${prefix} Press ${chalk_1.default.cyan('Ctrl+C')} to stop`);
155
+ logger_1.default.printLine(`Development server started. Watching for changes...`, 'info');
156
+ logger_1.default.printLine(`Press ${chalk_1.default.cyan('Ctrl+C')} to stop`, 'info');
192
157
  }
193
158
  }
194
159
  async restart() {
@@ -196,9 +161,6 @@ class DevRunner {
196
161
  if (!this.isRunning) {
197
162
  return;
198
163
  }
199
- if (this.options.showInfo) {
200
- logger.log(`${prefix} Restarting due to file changes...`);
201
- }
202
164
  this.restartCount++;
203
165
  // Stop current processes
204
166
  if (this.runner) {
@@ -210,9 +172,6 @@ class DevRunner {
210
172
  this.printDevBanner();
211
173
  // Run commands again
212
174
  await this.runCommands();
213
- if (this.options.showInfo) {
214
- logger.log(`${prefix} Restart completed. Watching for changes...`);
215
- }
216
175
  }
217
176
  async stop() {
218
177
  const prefix = chalk_1.default.cyan(`[${this.options.runnerName}]`);
@@ -220,7 +179,7 @@ class DevRunner {
220
179
  return;
221
180
  }
222
181
  if (this.options.showInfo) {
223
- logger.log(`${prefix} Stopping development server...`);
182
+ logger_1.default.printLine(`Stopping development server...`, 'info');
224
183
  }
225
184
  this.isRunning = false;
226
185
  // Stop file watcher
@@ -234,9 +193,9 @@ class DevRunner {
234
193
  const uptime = Math.floor((Date.now() - this.startTime.getTime()) / 1000);
235
194
  const uptimeStr = this.formatUptime(uptime);
236
195
  if (this.options.showInfo) {
237
- logger.log(`${prefix} ${this.options.runnerName} development server stopped after ${uptimeStr}`);
196
+ logger_1.default.printLine(`${this.options.runnerName} development server stopped after ${uptimeStr}`, 'info');
238
197
  if (this.restartCount > 0) {
239
- logger.log(`${prefix} Total restarts: ${this.restartCount}`);
198
+ logger_1.default.printLine(`Total restarts: ${this.restartCount}`, 'info');
240
199
  }
241
200
  }
242
201
  }
@@ -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,60 +20,28 @@ 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
- // Clear any existing spinner intervals
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.set(cmd, this.generateColor(cmd));
47
- });
48
- // Log commands that will be executed
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
- generateColor(command) {
57
- // Generate distinct colors for commands based on the command string
35
+ getRandomColor() {
58
36
  const vibrantColors = [
59
- '#00BFFF',
60
- '#32CD32',
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
- let hash = 0;
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) {
79
- const color = this.commandColors.get(command) || chalk_1.default.white;
80
- const prefix = `${command}:`.padEnd(this.prefixLength);
81
- return color(prefix);
44
+ return '';
82
45
  }
83
46
  bufferOutput(output) {
84
47
  const currentBuffer = this.outputBuffer.get(output.command) || [];
@@ -86,186 +49,92 @@ class Logger {
86
49
  this.outputBuffer.set(output.command, currentBuffer);
87
50
  }
88
51
  printBuffer(command) {
89
- const buffer = this.outputBuffer.get(command) || [];
90
- const color = this.commandColors.get(command) || chalk_1.default.white;
91
- // Stop spinner for this command if running
92
- this.stopSpinner(command);
93
- buffer.forEach(output => {
94
- const prefix = this.formatPrefix(output.command);
95
- const content = output.data.trim();
96
- if (content) {
97
- const lines = content.split('\n');
98
- lines.forEach(line => {
99
- if (line.trim()) {
100
- const outputLine = `${prefix} ${line}`;
101
- // Show stderr in appropriate colors
102
- if (output.type === 'stderr') {
103
- // Not all stderr is an error, check for warning or info patterns
104
- if (line.toLowerCase().includes('warn') || line.toLowerCase().includes('warning')) {
105
- console.log(`${prefix} ${chalk_1.default.yellow(line)}`);
106
- }
107
- else if (line.toLowerCase().includes('error')) {
108
- console.log(`${prefix} ${chalk_1.default.red(line)}`);
109
- }
110
- else {
111
- console.log(`${prefix} ${line}`);
112
- }
113
- }
114
- else {
115
- console.log(outputLine);
116
- }
117
- }
118
- });
119
- }
120
- });
121
- // Clear buffer after printing
122
- this.outputBuffer.set(command, []);
52
+ this.flushBuffer(command);
123
53
  }
124
54
  clearBuffer(command) {
125
55
  this.outputBuffer.set(command, []);
126
56
  }
127
- printLine(message, level = 'info') {
128
- if (level === 'error') {
129
- console.error(chalk_1.default.red(`${figures_1.default.cross} ${message}`));
130
- }
131
- else if (level === 'warn') {
132
- console.warn(chalk_1.default.yellow(`${figures_1.default.warning} ${message}`));
133
- }
134
- else {
135
- console.log(chalk_1.default.blue(`${figures_1.default.info} ${message}`));
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, []);
136
78
  }
137
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
+ }
138
86
  printStart(command) {
139
- // Record start time
140
87
  this.startTimes.set(command, new Date());
141
- const prefix = this.formatPrefix(command);
142
88
  const color = this.commandColors.get(command) || chalk_1.default.white;
143
- // Stop any previous spinner for this command (e.g. if retrying)
144
- this.stopSpinner(command);
145
- // Clear the line before printing "Starting..."
146
- if (this.isSpinnerActive) { // Check if any spinner was active to avoid clearing unnecessarily
147
- process.stdout.write('\r' + ' '.repeat(process.stdout.columns || 80) + '\r');
148
- }
149
- console.log(`${prefix} ${color('Starting...')}`);
150
- // Start spinner for this command
151
- this.startSpinner(command);
152
- }
153
- startSpinner(command) {
154
- // Only create a spinner if one doesn't already exist for this command
155
- if (this.spinnerIntervals.has(command)) {
156
- return;
157
- }
158
- this.isSpinnerActive = true;
159
- const color = this.commandColors.get(command) || chalk_1.default.white;
160
- const prefix = this.formatPrefix(command);
161
- const interval = setInterval(() => {
162
- const frame = this.getSpinnerFrame();
163
- process.stdout.write(`\r${prefix} ${color(frame)} ${chalk_1.default.dim('Running...')}`);
164
- }, 80);
165
- this.spinnerIntervals.set(command, interval);
166
- }
167
- stopSpinner(command) {
168
- const interval = this.spinnerIntervals.get(command);
169
- if (interval) {
170
- clearInterval(interval);
171
- this.spinnerIntervals.delete(command);
172
- // Clear the spinner line
173
- if (this.isSpinnerActive) {
174
- process.stdout.write('\r' + ' '.repeat(process.stdout.columns || 80) + '\r');
175
- }
176
- }
177
- }
178
- stopAllSpinners() {
179
- this.spinnerIntervals.forEach((interval, command) => {
180
- clearInterval(interval);
181
- });
182
- this.spinnerIntervals.clear();
183
- this.isSpinnerActive = false;
184
- // Clear the spinner line if any spinner was active
185
- if (this.isSpinnerActive) {
186
- process.stdout.write('\r' + ' '.repeat(process.stdout.columns || 80) + '\r');
187
- }
89
+ console.log(`${color('Starting...')}`);
188
90
  }
189
91
  printSuccess(result) {
190
92
  const { command, duration } = result;
191
- this.stopSpinner(command);
93
+ const color = this.commandColors.get(command) || chalk_1.default.green;
192
94
  const prefix = this.formatPrefix(command);
193
- const color = this.commandColors.get(command) || chalk_1.default.white;
194
- const durationStr = duration
195
- ? ` ${chalk_1.default.dim(`(${(duration / 1000).toFixed(2)}s)`)}`
196
- : '';
197
- console.log(`${prefix} ${chalk_1.default.green(figures_1.default.tick)} ${chalk_1.default.green('Completed')}${durationStr}`);
95
+ console.log(color(`${prefix}${figures_1.default.tick} Success! (${duration.toFixed(2)}ms)`));
198
96
  }
199
97
  printError(result) {
200
- const { command, error, code, duration } = result;
201
- this.stopSpinner(command);
98
+ const { command, duration, code } = result;
99
+ const color = this.commandColors.get(command) || chalk_1.default.red;
202
100
  const prefix = this.formatPrefix(command);
203
- const durationStr = duration ? ` ${chalk_1.default.dim(`(${(duration / 1000).toFixed(2)}s)`)}` : '';
204
- const errorCode = code !== null ? ` ${chalk_1.default.red(`[code: ${code}]`)}` : '';
205
- console.error(`${prefix} ${chalk_1.default.red(figures_1.default.cross)} ${chalk_1.default.red('Failed')}${errorCode}${durationStr}`);
206
- if (error) {
207
- console.error(`${prefix} ${chalk_1.default.red(error.message)}`);
208
- }
209
- }
210
- printEnd(result, minimalOutput) {
211
- this.stopSpinner(result.command);
212
- const prefix = this.formatPrefix(result.command); // Corrected to formatPrefix
213
- let durationDisplay = '';
214
- if (result.duration !== null) {
215
- // Ensure result.duration is treated as a number here
216
- durationDisplay = `(${(0, utils_1.formatDuration)(result.duration)})`;
217
- }
218
- const duration = durationDisplay;
219
- if (minimalOutput) {
220
- if (!result.success) {
221
- const status = result.code !== null ? `failed (code ${result.code})` : 'failed';
222
- this.printLine(`${prefix} ${chalk_1.default.red(figures_1.default.cross)} ${result.command} ${status} ${duration}`, 'error');
223
- }
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);
224
110
  }
225
111
  else {
226
- if (result.success) {
227
- this.printLine(`${prefix} ${chalk_1.default.green(figures_1.default.tick)} Command "${result.command}" finished successfully ${duration}`, 'info');
228
- }
229
- else {
230
- const errorCode = result.code !== null ? ` (code ${result.code})` : '';
231
- const errorMessage = result.error ? `: ${result.error.message}` : '';
232
- this.printLine(`${prefix} ${chalk_1.default.red(figures_1.default.cross)} Command "${result.command}" failed${errorCode}${errorMessage} ${duration}`, 'error');
233
- }
112
+ this.printError(result);
234
113
  }
235
114
  }
236
- printSummary(results) {
237
- // Stop any remaining spinners
238
- this.stopAllSpinners();
239
- const successful = results.filter(r => r.success).length;
240
- const failed = results.length - successful;
241
- const totalDuration = results.reduce((sum, result) => sum + (result.duration || 0), 0);
242
- const totalSeconds = (totalDuration / 1000).toFixed(2);
243
- console.log('\n' + chalk_1.default.bgHex('#0066FF').black(' Execution Summary ') + '\n');
244
- console.log(`${chalk_1.default.green(`${figures_1.default.tick} ${successful} succeeded`)}, ${chalk_1.default.red(`${figures_1.default.cross} ${failed} failed`)}`);
245
- console.log(`${chalk_1.default.blue(figures_1.default.info)} ${chalk_1.default.dim(`Total execution time: ${totalSeconds}s`)}`);
246
- if (successful > 0) {
247
- console.log('\n' + chalk_1.default.green.bold('Successful commands:'));
248
- results
249
- .filter(r => r.success)
250
- .forEach(result => {
251
- const color = this.commandColors.get(result.command) || chalk_1.default.white;
252
- const duration = result.duration
253
- ? chalk_1.default.dim(` (${(result.duration / 1000).toFixed(2)}s)`)
254
- : '';
255
- console.log(` ${chalk_1.default.green(figures_1.default.tick)} ${color(result.command)}${duration}`);
256
- });
257
- }
258
- if (failed > 0) {
259
- console.log('\n' + chalk_1.default.red.bold('Failed commands:'));
260
- results
261
- .filter(r => !r.success)
262
- .forEach(result => {
263
- const color = this.commandColors.get(result.command) || chalk_1.default.white;
264
- const duration = result.duration
265
- ? chalk_1.default.dim(` (${(result.duration / 1000).toFixed(2)}s)`)
266
- : '';
267
- const code = result.code !== null ? chalk_1.default.red(` [code: ${result.code}]`) : '';
268
- 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
+ }
269
138
  });
270
139
  }
271
140
  }
@@ -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); // Or packageJson.scripts[scriptName] if you want the script value
65
+ expandedCommands.push(scriptName);
69
66
  foundMatch = true;
70
67
  }
71
68
  }
72
69
  if (!foundMatch) {
73
- logger_1.default.printLine(`No scripts found in package.json matching wildcard: ${command}`, 'warn');
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 like package.json not found, or script not in package.json
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
- logger_1.default.printLine(`Failed to kill process ${proc.pid} (${command}): ${errInner.message}`, 'error');
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;
@@ -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
- logger_1.default.printLine(`Watching directory: ${chalk_1.default.cyan(absolutePath)}`, 'info');
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
- logger_1.default.printLine(`Failed to watch directory ${dirPath}: ${error.message}`, 'warn');
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
- logger_1.default.printLine(`Watching file: ${chalk_1.default.cyan(absolutePath)}`, 'info');
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
- logger_1.default.printLine(`Failed to watch file ${filePath}: ${error.message}`, 'warn');
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
- logger_1.default.printLine(`File ${eventType}: ${chalk_1.default.yellow(path.relative(process.cwd(), filePath))}`, 'info');
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) {
@@ -188,7 +183,6 @@ class FileWatcher extends events_1.EventEmitter {
188
183
  return;
189
184
  }
190
185
  this.isWatching = true;
191
- logger_1.default.printLine('Starting file watcher...', 'info');
192
186
  for (const watchPath of this.options.watch) {
193
187
  const absolutePath = path.resolve(watchPath);
194
188
  try {
@@ -201,20 +195,17 @@ class FileWatcher extends events_1.EventEmitter {
201
195
  }
202
196
  }
203
197
  catch (error) {
204
- logger_1.default.printLine(`Cannot watch ${watchPath}: ${error.message}`, 'warn');
198
+ // logger.printLine(`Cannot watch ${watchPath}: ${(error as Error).message}`, 'warn');
205
199
  }
206
200
  }
207
201
  const watchedCount = this.watchers.length;
208
- logger_1.default.printLine(`File watcher started. Monitoring ${chalk_1.default.green(watchedCount)} locations`, 'info');
209
202
  if (this.options.ext && this.options.ext.length > 0) {
210
- logger_1.default.printLine(`Watching extensions: ${chalk_1.default.cyan(this.options.ext.join(', '))}`, 'info');
211
203
  }
212
204
  }
213
205
  stop() {
214
206
  if (!this.isWatching) {
215
207
  return;
216
208
  }
217
- logger_1.default.printLine('Stopping file watcher...', 'info');
218
209
  this.watchers.forEach(watcher => {
219
210
  try {
220
211
  watcher.close();
@@ -230,7 +221,6 @@ class FileWatcher extends events_1.EventEmitter {
230
221
  clearTimeout(this.debounceTimer);
231
222
  this.debounceTimer = null;
232
223
  }
233
- logger_1.default.printLine('File watcher stopped', 'info');
234
224
  }
235
225
  isActive() {
236
226
  return this.isWatching;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neex",
3
- "version": "0.6.38",
3
+ "version": "0.6.40",
4
4
  "description": "The Modern Build System for Polyrepo-in-Monorepo Architecture",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",