neex 0.6.64 → 0.6.66

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.
@@ -159,90 +159,98 @@ class StartManager {
159
159
  this.log(`Process started (PID: ${this.masterProcess.pid}, Port: ${port})`);
160
160
  }
161
161
  }
162
- async startWorker(workerId) {
163
- var _a, _b;
164
- const nodeArgs = this.getNodeArgs();
165
- const port = this.options.port || 8000;
166
- const env = {
167
- ...process.env,
168
- NODE_ENV: process.env.NODE_ENV || 'production',
169
- WORKER_ID: workerId.toString(),
170
- PORT: port.toString(),
171
- CLUSTER_WORKER: 'true',
172
- FORCE_COLOR: this.options.color ? '1' : '0',
173
- NODE_OPTIONS: '--no-deprecation'
174
- };
175
- const workerProcess = (0, child_process_1.fork)(this.options.file, [], {
176
- cwd: this.options.workingDir,
177
- env,
178
- execArgv: nodeArgs,
179
- silent: true
180
- });
181
- const workerInfo = {
182
- process: workerProcess,
183
- pid: workerProcess.pid,
184
- restarts: 0,
185
- startTime: new Date(),
186
- id: workerId,
187
- port: port
188
- };
189
- this.workers.set(workerId, workerInfo);
190
- // Handle worker output
191
- (_a = workerProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
192
- const message = data.toString().trim();
193
- if (message && !message.includes('[dotenv@') && !message.includes('injecting env')) {
194
- const prefix = this.options.verbose ?
195
- chalk_1.default.dim(`[Worker ${workerId}] `) : '';
196
- console.log(prefix + message);
197
- }
198
- });
199
- (_b = workerProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
200
- const message = data.toString().trim();
201
- if (message && !message.includes('[dotenv@') && !message.includes('injecting env')) {
202
- const prefix = this.options.verbose ?
203
- chalk_1.default.dim(`[Worker ${workerId}] `) : '';
204
- console.error(prefix + chalk_1.default.red(message));
205
- }
206
- });
207
- workerProcess.on('error', (error) => {
208
- this.log(`Worker ${workerId} error: ${error.message}`, 'error');
209
- });
210
- workerProcess.on('exit', (code, signal) => {
211
- this.workers.delete(workerId);
212
- if (!this.isShuttingDown && code !== 0 && signal !== 'SIGTERM') {
213
- this.log(`Worker ${workerId} crashed (code: ${code}, signal: ${signal})`, 'error');
214
- this.restartWorker(workerId);
215
- }
216
- });
217
- // Wait for worker to be ready
218
- await new Promise((resolve, reject) => {
219
- const timeout = setTimeout(() => {
220
- resolve(); // Don't reject, assume it's ready
221
- }, 5000);
222
- workerProcess.on('message', (message) => {
162
+ startWorker(workerId) {
163
+ return new Promise((resolve, reject) => {
164
+ var _a, _b;
165
+ const nodeArgs = this.getNodeArgs();
166
+ const port = this.options.port || 8000;
167
+ const env = {
168
+ ...process.env,
169
+ NODE_ENV: process.env.NODE_ENV || 'production',
170
+ WORKER_ID: workerId.toString(),
171
+ PORT: port.toString(),
172
+ CLUSTER_WORKER: 'true',
173
+ FORCE_COLOR: this.options.color ? '1' : '0',
174
+ NODE_OPTIONS: '--no-deprecation'
175
+ };
176
+ const workerProcess = (0, child_process_1.fork)(this.options.file, [], {
177
+ cwd: this.options.workingDir,
178
+ env,
179
+ execArgv: nodeArgs,
180
+ silent: true
181
+ });
182
+ const workerInfo = {
183
+ process: workerProcess,
184
+ pid: workerProcess.pid,
185
+ restarts: 0,
186
+ startTime: new Date(),
187
+ id: workerId,
188
+ port: port
189
+ };
190
+ this.workers.set(workerId, workerInfo);
191
+ let isReady = false;
192
+ const readinessTimeout = setTimeout(() => {
193
+ if (!isReady) {
194
+ workerProcess.kill();
195
+ reject(new Error(`Worker ${workerId} failed to become ready within 15s.`));
196
+ }
197
+ }, 15000);
198
+ const cleanupReadinessListeners = () => {
199
+ var _a;
200
+ clearTimeout(readinessTimeout);
201
+ (_a = workerProcess.stdout) === null || _a === void 0 ? void 0 : _a.removeListener('data', onDataForReady);
202
+ workerProcess.removeListener('message', onMessageForReady);
203
+ };
204
+ const onReady = () => {
205
+ if (isReady)
206
+ return;
207
+ isReady = true;
208
+ cleanupReadinessListeners();
209
+ if (this.options.verbose) {
210
+ this.log(`Worker ${workerId} is ready (PID: ${workerProcess.pid})`);
211
+ }
212
+ resolve(workerInfo);
213
+ };
214
+ const onDataForReady = (data) => {
215
+ const message = data.toString();
216
+ const prefix = chalk_1.default.dim(`[Worker ${workerId}] `);
217
+ process.stdout.write(prefix + message);
218
+ if (/listening|ready|running on port|local:/i.test(message)) {
219
+ onReady();
220
+ }
221
+ };
222
+ const onMessageForReady = (message) => {
223
223
  if (message && message.type === 'ready') {
224
- clearTimeout(timeout);
225
- resolve();
224
+ onReady();
226
225
  }
226
+ };
227
+ (_a = workerProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', onDataForReady);
228
+ (_b = workerProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
229
+ const prefix = chalk_1.default.red.dim(`[Worker ${workerId}] `);
230
+ process.stderr.write(prefix + data.toString());
227
231
  });
232
+ workerProcess.on('message', onMessageForReady);
228
233
  workerProcess.on('error', (error) => {
229
- clearTimeout(timeout);
230
- reject(error);
234
+ if (!isReady) {
235
+ cleanupReadinessListeners();
236
+ reject(error);
237
+ }
238
+ this.log(`Worker ${workerId} error: ${error.message}`, 'error');
231
239
  });
232
- workerProcess.on('exit', (code) => {
233
- clearTimeout(timeout);
234
- if (code !== 0) {
235
- reject(new Error(`Worker ${workerId} exited with code ${code}`));
240
+ workerProcess.on('exit', (code, signal) => {
241
+ if (!isReady) {
242
+ cleanupReadinessListeners();
243
+ reject(new Error(`Worker ${workerId} exited with code ${code} before becoming ready.`));
236
244
  }
237
245
  else {
238
- resolve();
246
+ this.workers.delete(workerId);
247
+ if (!this.isShuttingDown && code !== 0 && signal !== 'SIGTERM') {
248
+ this.log(`Worker ${workerId} crashed (code: ${code}, signal: ${signal})`, 'error');
249
+ this.restartWorker(workerId);
250
+ }
239
251
  }
240
252
  });
241
253
  });
242
- if (this.options.verbose) {
243
- this.log(`Worker ${workerId} started (PID: ${workerProcess.pid})`);
244
- }
245
- return workerInfo;
246
254
  }
247
255
  async restartWorker(workerId) {
248
256
  const workerInfo = this.workers.get(workerId);
@@ -290,16 +298,20 @@ class StartManager {
290
298
  return;
291
299
  }
292
300
  // Multi-worker mode
301
+ this.log(`${chalk_1.default.blue(figures_1.default.play)} Starting production server (${this.options.workers} workers)`);
293
302
  const startPromises = [];
294
303
  for (let i = 0; i < this.options.workers; i++) {
295
304
  startPromises.push(this.startWorker(i + 1));
296
305
  }
297
306
  try {
298
307
  await Promise.all(startPromises);
308
+ this.log(`${chalk_1.default.green(figures_1.default.tick)} Server ready on port ${this.options.port || 8000} (${this.workers.size} workers)`);
299
309
  }
300
310
  catch (error) {
301
311
  this.log(`Failed to start some workers: ${error.message}`, 'error');
302
- // Continue with successfully started workers
312
+ if (this.workers.size > 0) {
313
+ this.log(`${chalk_1.default.yellow(figures_1.default.warning)} Server partially ready on port ${this.options.port || 8000} (${this.workers.size} workers)`);
314
+ }
303
315
  }
304
316
  }
305
317
  setupHealthCheck() {
@@ -420,11 +432,6 @@ class StartManager {
420
432
  this.setupWatcher();
421
433
  // Start the application
422
434
  await this.startCluster();
423
- // Success message
424
- const port = this.options.port || 8000;
425
- const workerInfo = this.options.workers === 1 ?
426
- '' : ` (${this.workers.size} workers)`;
427
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.tick)} Server ready on port ${port}${workerInfo}`, 'info');
428
435
  }
429
436
  catch (error) {
430
437
  this.log(`Failed to start server: ${error.message}`, 'error');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neex",
3
- "version": "0.6.64",
3
+ "version": "0.6.66",
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",