neex 0.6.65 → 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,97 +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
- // Suppress common startup messages from workers
194
- if (message &&
195
- !message.includes('[dotenv@') &&
196
- !message.includes('injecting env') &&
197
- !/express/i.test(message) &&
198
- !/local:/i.test(message) &&
199
- !/health check:/i.test(message) &&
200
- !/environment:/i.test(message)) {
201
- const prefix = this.options.verbose ?
202
- chalk_1.default.dim(`[Worker ${workerId}] `) : '';
203
- console.log(prefix + message);
204
- }
205
- });
206
- (_b = workerProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
207
- const message = data.toString().trim();
208
- if (message && !message.includes('[dotenv@') && !message.includes('injecting env')) {
209
- const prefix = this.options.verbose ?
210
- chalk_1.default.dim(`[Worker ${workerId}] `) : '';
211
- console.error(prefix + chalk_1.default.red(message));
212
- }
213
- });
214
- workerProcess.on('error', (error) => {
215
- this.log(`Worker ${workerId} error: ${error.message}`, 'error');
216
- });
217
- workerProcess.on('exit', (code, signal) => {
218
- this.workers.delete(workerId);
219
- if (!this.isShuttingDown && code !== 0 && signal !== 'SIGTERM') {
220
- this.log(`Worker ${workerId} crashed (code: ${code}, signal: ${signal})`, 'error');
221
- this.restartWorker(workerId);
222
- }
223
- });
224
- // Wait for worker to be ready
225
- await new Promise((resolve, reject) => {
226
- const timeout = setTimeout(() => {
227
- resolve(); // Don't reject, assume it's ready
228
- }, 5000);
229
- 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) => {
230
223
  if (message && message.type === 'ready') {
231
- clearTimeout(timeout);
232
- resolve();
224
+ onReady();
233
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());
234
231
  });
232
+ workerProcess.on('message', onMessageForReady);
235
233
  workerProcess.on('error', (error) => {
236
- clearTimeout(timeout);
237
- reject(error);
234
+ if (!isReady) {
235
+ cleanupReadinessListeners();
236
+ reject(error);
237
+ }
238
+ this.log(`Worker ${workerId} error: ${error.message}`, 'error');
238
239
  });
239
- workerProcess.on('exit', (code) => {
240
- clearTimeout(timeout);
241
- if (code !== 0) {
242
- 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.`));
243
244
  }
244
245
  else {
245
- 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
+ }
246
251
  }
247
252
  });
248
253
  });
249
- if (this.options.verbose) {
250
- this.log(`Worker ${workerId} started (PID: ${workerProcess.pid})`);
251
- }
252
- return workerInfo;
253
254
  }
254
255
  async restartWorker(workerId) {
255
256
  const workerInfo = this.workers.get(workerId);
@@ -308,9 +309,8 @@ class StartManager {
308
309
  }
309
310
  catch (error) {
310
311
  this.log(`Failed to start some workers: ${error.message}`, 'error');
311
- // Continue with successfully started workers
312
312
  if (this.workers.size > 0) {
313
- this.log(`${chalk_1.default.green(figures_1.default.tick)} Server partially ready on port ${this.options.port || 8000} (${this.workers.size} workers)`);
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
314
  }
315
315
  }
316
316
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neex",
3
- "version": "0.6.65",
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",