neex 0.7.44 → 0.8.3
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 +50 -326
- package/bin/neex +31 -0
- package/install.js +94 -0
- package/package.json +30 -63
- package/dist/bin/neex.d.ts +0 -26
- package/dist/bin/neex.d.ts.map +0 -1
- package/dist/bin/neex.js +0 -8
- package/dist/src/build-manager.d.ts +0 -41
- package/dist/src/build-manager.d.ts.map +0 -1
- package/dist/src/build-manager.js +0 -369
- package/dist/src/cli.d.ts +0 -2
- package/dist/src/cli.d.ts.map +0 -1
- package/dist/src/cli.js +0 -67
- package/dist/src/commands/add-commands.d.ts +0 -4
- package/dist/src/commands/add-commands.d.ts.map +0 -1
- package/dist/src/commands/add-commands.js +0 -83
- package/dist/src/commands/build-commands.d.ts +0 -5
- package/dist/src/commands/build-commands.d.ts.map +0 -1
- package/dist/src/commands/build-commands.js +0 -123
- package/dist/src/commands/dev-commands.d.ts +0 -5
- package/dist/src/commands/dev-commands.d.ts.map +0 -1
- package/dist/src/commands/dev-commands.js +0 -198
- package/dist/src/commands/index.d.ts +0 -8
- package/dist/src/commands/index.d.ts.map +0 -1
- package/dist/src/commands/index.js +0 -27
- package/dist/src/commands/init-commands.d.ts +0 -2
- package/dist/src/commands/init-commands.d.ts.map +0 -1
- package/dist/src/commands/init-commands.js +0 -20
- package/dist/src/commands/run-commands.d.ts +0 -3
- package/dist/src/commands/run-commands.d.ts.map +0 -1
- package/dist/src/commands/run-commands.js +0 -93
- package/dist/src/commands/server-commands.d.ts +0 -3
- package/dist/src/commands/server-commands.d.ts.map +0 -1
- package/dist/src/commands/server-commands.js +0 -51
- package/dist/src/commands/start-commands.d.ts +0 -5
- package/dist/src/commands/start-commands.d.ts.map +0 -1
- package/dist/src/commands/start-commands.js +0 -162
- package/dist/src/dev-manager.d.ts +0 -51
- package/dist/src/dev-manager.d.ts.map +0 -1
- package/dist/src/dev-manager.js +0 -471
- package/dist/src/index.d.ts +0 -41
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -70
- package/dist/src/logger-manager.d.ts +0 -4
- package/dist/src/logger-manager.d.ts.map +0 -1
- package/dist/src/logger-manager.js +0 -17
- package/dist/src/logger.d.ts +0 -34
- package/dist/src/logger.d.ts.map +0 -1
- package/dist/src/logger.js +0 -279
- package/dist/src/runner.d.ts +0 -21
- package/dist/src/runner.d.ts.map +0 -1
- package/dist/src/runner.js +0 -414
- package/dist/src/start-manager.d.ts +0 -49
- package/dist/src/start-manager.d.ts.map +0 -1
- package/dist/src/start-manager.js +0 -484
- package/dist/src/types.d.ts +0 -41
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js +0 -2
- package/dist/src/utils.d.ts +0 -2
- package/dist/src/utils.d.ts.map +0 -1
- package/dist/src/utils.js +0 -9
|
@@ -1,484 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.StartManager = void 0;
|
|
7
|
-
// src/start-manager.ts - Fixed production start manager
|
|
8
|
-
const child_process_1 = require("child_process");
|
|
9
|
-
const chokidar_1 = require("chokidar");
|
|
10
|
-
const logger_manager_js_1 = require("./logger-manager.js");
|
|
11
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
-
const figures_1 = __importDefault(require("figures"));
|
|
13
|
-
const path_1 = __importDefault(require("path"));
|
|
14
|
-
const fs_1 = __importDefault(require("fs"));
|
|
15
|
-
const http_1 = __importDefault(require("http"));
|
|
16
|
-
const lodash_1 = require("lodash");
|
|
17
|
-
const os_1 = __importDefault(require("os"));
|
|
18
|
-
class StartManager {
|
|
19
|
-
options;
|
|
20
|
-
workers = new Map();
|
|
21
|
-
watcher = null;
|
|
22
|
-
healthServer = null;
|
|
23
|
-
isShuttingDown = false;
|
|
24
|
-
debouncedRestart;
|
|
25
|
-
startTime;
|
|
26
|
-
totalRestarts = 0;
|
|
27
|
-
envLoaded = false;
|
|
28
|
-
masterProcess = null;
|
|
29
|
-
constructor(options) {
|
|
30
|
-
this.options = options;
|
|
31
|
-
this.startTime = new Date();
|
|
32
|
-
this.debouncedRestart = (0, lodash_1.debounce)(this.restartAll.bind(this), options.restartDelay);
|
|
33
|
-
}
|
|
34
|
-
log(message, level = 'info') {
|
|
35
|
-
logger_manager_js_1.loggerManager.printLine(message, level);
|
|
36
|
-
}
|
|
37
|
-
loadEnvFile() {
|
|
38
|
-
if (this.envLoaded)
|
|
39
|
-
return;
|
|
40
|
-
if (this.options.envFile && fs_1.default.existsSync(this.options.envFile)) {
|
|
41
|
-
try {
|
|
42
|
-
const envContent = fs_1.default.readFileSync(this.options.envFile, 'utf8');
|
|
43
|
-
const lines = envContent.split('\n');
|
|
44
|
-
let loadedCount = 0;
|
|
45
|
-
for (const line of lines) {
|
|
46
|
-
const trimmed = line.trim();
|
|
47
|
-
if (trimmed && !trimmed.startsWith('#')) {
|
|
48
|
-
const [key, ...values] = trimmed.split('=');
|
|
49
|
-
if (key && values.length > 0) {
|
|
50
|
-
const value = values.join('=').trim();
|
|
51
|
-
const cleanValue = value.replace(/^["']|["']$/g, '');
|
|
52
|
-
if (!process.env[key.trim()]) {
|
|
53
|
-
process.env[key.trim()] = cleanValue;
|
|
54
|
-
loadedCount++;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (this.options.verbose && loadedCount > 0) {
|
|
60
|
-
this.log(`Loaded ${loadedCount} environment variables from ${this.options.envFile}`);
|
|
61
|
-
}
|
|
62
|
-
this.envLoaded = true;
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
if (this.options.verbose) {
|
|
66
|
-
this.log(`Failed to load environment file: ${error.message}`, 'warn');
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
parseMemoryLimit(limit) {
|
|
72
|
-
if (!limit)
|
|
73
|
-
return undefined;
|
|
74
|
-
const match = limit.match(/^(\d+)([KMGT]?)$/i);
|
|
75
|
-
if (!match)
|
|
76
|
-
return undefined;
|
|
77
|
-
const value = parseInt(match[1]);
|
|
78
|
-
const unit = match[2]?.toUpperCase() || '';
|
|
79
|
-
const multipliers = {
|
|
80
|
-
K: 1024,
|
|
81
|
-
M: 1024 * 1024,
|
|
82
|
-
G: 1024 * 1024 * 1024,
|
|
83
|
-
T: 1024 * 1024 * 1024 * 1024,
|
|
84
|
-
};
|
|
85
|
-
return value * (multipliers[unit] || 1);
|
|
86
|
-
}
|
|
87
|
-
getNodeArgs() {
|
|
88
|
-
const args = [];
|
|
89
|
-
if (this.options.memoryLimit) {
|
|
90
|
-
const memoryBytes = this.parseMemoryLimit(this.options.memoryLimit);
|
|
91
|
-
if (memoryBytes) {
|
|
92
|
-
const memoryMB = Math.floor(memoryBytes / (1024 * 1024));
|
|
93
|
-
args.push(`--max-old-space-size=${memoryMB}`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (this.options.inspect) {
|
|
97
|
-
args.push('--inspect');
|
|
98
|
-
}
|
|
99
|
-
if (this.options.inspectBrk) {
|
|
100
|
-
args.push('--inspect-brk');
|
|
101
|
-
}
|
|
102
|
-
if (this.options.nodeArgs) {
|
|
103
|
-
args.push(...this.options.nodeArgs.split(' ').filter(arg => arg.trim()));
|
|
104
|
-
}
|
|
105
|
-
return args;
|
|
106
|
-
}
|
|
107
|
-
async startSingleProcess() {
|
|
108
|
-
const nodeArgs = this.getNodeArgs();
|
|
109
|
-
const port = this.options.port || 8000;
|
|
110
|
-
const env = {
|
|
111
|
-
...process.env,
|
|
112
|
-
NODE_ENV: process.env.NODE_ENV || 'production',
|
|
113
|
-
PORT: port.toString(),
|
|
114
|
-
FORCE_COLOR: this.options.color ? '1' : '0',
|
|
115
|
-
NODE_OPTIONS: '--no-deprecation',
|
|
116
|
-
};
|
|
117
|
-
this.masterProcess = (0, child_process_1.fork)(this.options.file, [], {
|
|
118
|
-
cwd: this.options.workingDir,
|
|
119
|
-
env,
|
|
120
|
-
execArgv: nodeArgs,
|
|
121
|
-
silent: false, // Let the process handle its own output
|
|
122
|
-
});
|
|
123
|
-
this.masterProcess.on('error', error => {
|
|
124
|
-
this.log(`Process error: ${error.message}`, 'error');
|
|
125
|
-
});
|
|
126
|
-
this.masterProcess.on('exit', (code, signal) => {
|
|
127
|
-
if (!this.isShuttingDown && code !== 0 && signal !== 'SIGTERM') {
|
|
128
|
-
this.log(`Process crashed (code: ${code}, signal: ${signal})`, 'error');
|
|
129
|
-
this.totalRestarts++;
|
|
130
|
-
if (this.totalRestarts < this.options.maxCrashes) {
|
|
131
|
-
setTimeout(() => {
|
|
132
|
-
this.startSingleProcess();
|
|
133
|
-
}, this.options.restartDelay);
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
this.log(`Max crashes reached (${this.options.maxCrashes}), not restarting`, 'error');
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
// Wait for process to be ready
|
|
141
|
-
await new Promise((resolve, reject) => {
|
|
142
|
-
const timeout = setTimeout(() => {
|
|
143
|
-
resolve(); // Don't reject, assume it's ready
|
|
144
|
-
}, 5000);
|
|
145
|
-
this.masterProcess.on('message', (message) => {
|
|
146
|
-
if (message && message.type === 'ready') {
|
|
147
|
-
clearTimeout(timeout);
|
|
148
|
-
resolve();
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
this.masterProcess.on('error', error => {
|
|
152
|
-
clearTimeout(timeout);
|
|
153
|
-
reject(error);
|
|
154
|
-
});
|
|
155
|
-
this.masterProcess.on('exit', code => {
|
|
156
|
-
clearTimeout(timeout);
|
|
157
|
-
if (code !== 0) {
|
|
158
|
-
reject(new Error(`Process exited with code ${code}`));
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
resolve();
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
if (this.options.verbose) {
|
|
166
|
-
this.log(`Process started (PID: ${this.masterProcess.pid}, Port: ${port})`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
startWorker(workerId) {
|
|
170
|
-
return new Promise((resolve, reject) => {
|
|
171
|
-
const nodeArgs = this.getNodeArgs();
|
|
172
|
-
const port = this.options.port || 8000;
|
|
173
|
-
const env = {
|
|
174
|
-
...process.env,
|
|
175
|
-
NODE_ENV: process.env.NODE_ENV || 'production',
|
|
176
|
-
WORKER_ID: workerId.toString(),
|
|
177
|
-
PORT: port.toString(),
|
|
178
|
-
CLUSTER_WORKER: 'true',
|
|
179
|
-
FORCE_COLOR: this.options.color ? '1' : '0',
|
|
180
|
-
NODE_OPTIONS: '--no-deprecation',
|
|
181
|
-
};
|
|
182
|
-
const workerProcess = (0, child_process_1.fork)(this.options.file, [], {
|
|
183
|
-
cwd: this.options.workingDir,
|
|
184
|
-
env,
|
|
185
|
-
execArgv: nodeArgs,
|
|
186
|
-
silent: true,
|
|
187
|
-
});
|
|
188
|
-
const workerInfo = {
|
|
189
|
-
process: workerProcess,
|
|
190
|
-
pid: workerProcess.pid,
|
|
191
|
-
restarts: 0,
|
|
192
|
-
startTime: new Date(),
|
|
193
|
-
id: workerId,
|
|
194
|
-
port: port,
|
|
195
|
-
};
|
|
196
|
-
this.workers.set(workerId, workerInfo);
|
|
197
|
-
let isReady = false;
|
|
198
|
-
const readinessTimeout = setTimeout(() => {
|
|
199
|
-
if (!isReady) {
|
|
200
|
-
workerProcess.kill();
|
|
201
|
-
reject(new Error(`Worker ${workerId} failed to become ready within 15s.`));
|
|
202
|
-
}
|
|
203
|
-
}, 15000);
|
|
204
|
-
const cleanupReadinessListeners = () => {
|
|
205
|
-
clearTimeout(readinessTimeout);
|
|
206
|
-
workerProcess.stdout?.removeListener('data', onDataForReady);
|
|
207
|
-
workerProcess.removeListener('message', onMessageForReady);
|
|
208
|
-
};
|
|
209
|
-
const onReady = () => {
|
|
210
|
-
if (isReady)
|
|
211
|
-
return;
|
|
212
|
-
isReady = true;
|
|
213
|
-
cleanupReadinessListeners();
|
|
214
|
-
if (this.options.verbose) {
|
|
215
|
-
this.log(`Worker ${workerId} is ready (PID: ${workerProcess.pid})`);
|
|
216
|
-
}
|
|
217
|
-
resolve(workerInfo);
|
|
218
|
-
};
|
|
219
|
-
const onDataForReady = (data) => {
|
|
220
|
-
const message = data.toString();
|
|
221
|
-
const prefix = chalk_1.default.dim(`[Worker ${workerId}] `);
|
|
222
|
-
process.stdout.write(prefix + message);
|
|
223
|
-
if (/listening|ready|running on port|local:/i.test(message)) {
|
|
224
|
-
onReady();
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
const onMessageForReady = (message) => {
|
|
228
|
-
if (message && message.type === 'ready') {
|
|
229
|
-
onReady();
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
|
-
workerProcess.stdout?.on('data', onDataForReady);
|
|
233
|
-
workerProcess.stderr?.on('data', data => {
|
|
234
|
-
const prefix = chalk_1.default.red.dim(`[Worker ${workerId}] `);
|
|
235
|
-
process.stderr.write(prefix + data.toString());
|
|
236
|
-
});
|
|
237
|
-
workerProcess.on('message', onMessageForReady);
|
|
238
|
-
workerProcess.on('error', error => {
|
|
239
|
-
if (!isReady) {
|
|
240
|
-
cleanupReadinessListeners();
|
|
241
|
-
reject(error);
|
|
242
|
-
}
|
|
243
|
-
this.log(`Worker ${workerId} error: ${error.message}`, 'error');
|
|
244
|
-
});
|
|
245
|
-
workerProcess.on('exit', (code, signal) => {
|
|
246
|
-
if (!isReady) {
|
|
247
|
-
cleanupReadinessListeners();
|
|
248
|
-
reject(new Error(`Worker ${workerId} exited with code ${code} before becoming ready.`));
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
this.workers.delete(workerId);
|
|
252
|
-
if (!this.isShuttingDown && code !== 0 && signal !== 'SIGTERM') {
|
|
253
|
-
this.log(`Worker ${workerId} crashed (code: ${code}, signal: ${signal})`, 'error');
|
|
254
|
-
this.restartWorker(workerId);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
async restartWorker(workerId) {
|
|
261
|
-
const workerInfo = this.workers.get(workerId);
|
|
262
|
-
if (workerInfo) {
|
|
263
|
-
workerInfo.restarts++;
|
|
264
|
-
this.totalRestarts++;
|
|
265
|
-
if (workerInfo.restarts >= this.options.maxCrashes) {
|
|
266
|
-
this.log(`Worker ${workerId} reached max crashes (${this.options.maxCrashes}), not restarting`, 'error');
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
if (this.options.verbose) {
|
|
270
|
-
this.log(`Restarting worker ${workerId} (attempt ${workerInfo.restarts})`);
|
|
271
|
-
}
|
|
272
|
-
try {
|
|
273
|
-
workerInfo.process.kill('SIGTERM');
|
|
274
|
-
await this.waitForProcessExit(workerInfo.process, 5000);
|
|
275
|
-
}
|
|
276
|
-
catch (error) {
|
|
277
|
-
workerInfo.process.kill('SIGKILL');
|
|
278
|
-
}
|
|
279
|
-
setTimeout(() => {
|
|
280
|
-
this.startWorker(workerId);
|
|
281
|
-
}, this.options.restartDelay);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
async waitForProcessExit(process, timeout) {
|
|
285
|
-
return new Promise((resolve, reject) => {
|
|
286
|
-
const timer = setTimeout(() => {
|
|
287
|
-
reject(new Error('Process exit timeout'));
|
|
288
|
-
}, timeout);
|
|
289
|
-
process.on('exit', () => {
|
|
290
|
-
clearTimeout(timer);
|
|
291
|
-
resolve();
|
|
292
|
-
});
|
|
293
|
-
if (process.killed) {
|
|
294
|
-
clearTimeout(timer);
|
|
295
|
-
resolve();
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
async startCluster() {
|
|
300
|
-
if (this.options.workers === 1) {
|
|
301
|
-
// Single process mode
|
|
302
|
-
await this.startSingleProcess();
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
// Multi-worker mode
|
|
306
|
-
this.log(`${chalk_1.default.blue(figures_1.default.play)} Starting production server (${this.options.workers} workers)`);
|
|
307
|
-
const startPromises = [];
|
|
308
|
-
for (let i = 0; i < this.options.workers; i++) {
|
|
309
|
-
startPromises.push(this.startWorker(i + 1));
|
|
310
|
-
}
|
|
311
|
-
try {
|
|
312
|
-
await Promise.all(startPromises);
|
|
313
|
-
this.log(`${chalk_1.default.green(figures_1.default.tick)} Server ready on port ${this.options.port || 8000} (${this.workers.size} workers)`);
|
|
314
|
-
}
|
|
315
|
-
catch (error) {
|
|
316
|
-
this.log(`Failed to start some workers: ${error.message}`, 'error');
|
|
317
|
-
if (this.workers.size > 0) {
|
|
318
|
-
this.log(`${chalk_1.default.yellow(figures_1.default.warning)} Server partially ready on port ${this.options.port || 8000} (${this.workers.size} workers)`);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
setupHealthCheck() {
|
|
323
|
-
if (!this.options.healthCheck)
|
|
324
|
-
return;
|
|
325
|
-
this.healthServer = http_1.default.createServer((req, res) => {
|
|
326
|
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
327
|
-
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
328
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
329
|
-
if (req.method === 'OPTIONS') {
|
|
330
|
-
res.writeHead(200);
|
|
331
|
-
res.end();
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
if (req.url === '/health') {
|
|
335
|
-
const stats = {
|
|
336
|
-
status: 'ok',
|
|
337
|
-
uptime: Date.now() - this.startTime.getTime(),
|
|
338
|
-
workers: this.workers.size,
|
|
339
|
-
activeWorkers: Array.from(this.workers.values()).map(w => ({
|
|
340
|
-
id: w.id,
|
|
341
|
-
pid: w.pid,
|
|
342
|
-
restarts: w.restarts,
|
|
343
|
-
uptime: Date.now() - w.startTime.getTime(),
|
|
344
|
-
})),
|
|
345
|
-
totalRestarts: this.totalRestarts,
|
|
346
|
-
memory: process.memoryUsage(),
|
|
347
|
-
cpu: os_1.default.loadavg(),
|
|
348
|
-
port: this.options.port || 8000,
|
|
349
|
-
};
|
|
350
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
351
|
-
res.end(JSON.stringify(stats, null, 2));
|
|
352
|
-
}
|
|
353
|
-
else {
|
|
354
|
-
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
355
|
-
res.end('Not Found');
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
this.healthServer.listen(this.options.healthPort, () => {
|
|
359
|
-
if (this.options.verbose) {
|
|
360
|
-
this.log(`Health endpoint: http://localhost:${this.options.healthPort}/health`);
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
setupWatcher() {
|
|
365
|
-
if (!this.options.watch)
|
|
366
|
-
return;
|
|
367
|
-
const watchPatterns = [
|
|
368
|
-
`${this.options.workingDir}/**/*.js`,
|
|
369
|
-
`${this.options.workingDir}/**/*.json`,
|
|
370
|
-
`${this.options.workingDir}/**/*.env*`,
|
|
371
|
-
];
|
|
372
|
-
this.watcher = (0, chokidar_1.watch)(watchPatterns, {
|
|
373
|
-
ignored: ['**/node_modules/**', '**/.git/**', '**/logs/**', '**/tmp/**'],
|
|
374
|
-
ignoreInitial: true,
|
|
375
|
-
atomic: 300,
|
|
376
|
-
awaitWriteFinish: {
|
|
377
|
-
stabilityThreshold: 2000,
|
|
378
|
-
pollInterval: 100,
|
|
379
|
-
},
|
|
380
|
-
});
|
|
381
|
-
this.watcher.on('change', (filePath) => {
|
|
382
|
-
if (this.options.verbose) {
|
|
383
|
-
this.log(`File changed: ${path_1.default.relative(this.options.workingDir, filePath)}`);
|
|
384
|
-
}
|
|
385
|
-
this.debouncedRestart();
|
|
386
|
-
});
|
|
387
|
-
this.watcher.on('error', (error) => {
|
|
388
|
-
this.log(`Watcher error: ${error.message}`, 'error');
|
|
389
|
-
});
|
|
390
|
-
if (this.options.verbose) {
|
|
391
|
-
this.log('File watching enabled');
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
async restartAll() {
|
|
395
|
-
if (this.isShuttingDown)
|
|
396
|
-
return;
|
|
397
|
-
this.log('Restarting due to file changes...');
|
|
398
|
-
if (this.options.workers === 1 && this.masterProcess) {
|
|
399
|
-
// Single process restart
|
|
400
|
-
try {
|
|
401
|
-
this.masterProcess.kill('SIGTERM');
|
|
402
|
-
await this.waitForProcessExit(this.masterProcess, 5000);
|
|
403
|
-
}
|
|
404
|
-
catch (error) {
|
|
405
|
-
this.masterProcess.kill('SIGKILL');
|
|
406
|
-
}
|
|
407
|
-
setTimeout(() => {
|
|
408
|
-
this.startSingleProcess();
|
|
409
|
-
}, this.options.restartDelay);
|
|
410
|
-
}
|
|
411
|
-
else {
|
|
412
|
-
// Multi-worker restart
|
|
413
|
-
const restartPromises = [];
|
|
414
|
-
for (const [workerId, workerInfo] of this.workers.entries()) {
|
|
415
|
-
restartPromises.push((async () => {
|
|
416
|
-
try {
|
|
417
|
-
workerInfo.process.kill('SIGTERM');
|
|
418
|
-
await this.waitForProcessExit(workerInfo.process, 5000);
|
|
419
|
-
}
|
|
420
|
-
catch (error) {
|
|
421
|
-
workerInfo.process.kill('SIGKILL');
|
|
422
|
-
}
|
|
423
|
-
})());
|
|
424
|
-
}
|
|
425
|
-
await Promise.allSettled(restartPromises);
|
|
426
|
-
setTimeout(() => {
|
|
427
|
-
this.startCluster();
|
|
428
|
-
}, this.options.restartDelay);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
async start() {
|
|
432
|
-
try {
|
|
433
|
-
// Load environment variables
|
|
434
|
-
this.loadEnvFile();
|
|
435
|
-
// Set up monitoring and health checks
|
|
436
|
-
this.setupHealthCheck();
|
|
437
|
-
this.setupWatcher();
|
|
438
|
-
// Start the application
|
|
439
|
-
await this.startCluster();
|
|
440
|
-
}
|
|
441
|
-
catch (error) {
|
|
442
|
-
this.log(`Failed to start server: ${error.message}`, 'error');
|
|
443
|
-
throw error;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
async stop() {
|
|
447
|
-
if (this.isShuttingDown)
|
|
448
|
-
return;
|
|
449
|
-
this.isShuttingDown = true;
|
|
450
|
-
this.log(`${chalk_1.default.yellow('⏹')} Shutting down gracefully...`);
|
|
451
|
-
if (this.watcher) {
|
|
452
|
-
await this.watcher.close();
|
|
453
|
-
}
|
|
454
|
-
if (this.healthServer) {
|
|
455
|
-
this.healthServer.close();
|
|
456
|
-
}
|
|
457
|
-
// Stop single process
|
|
458
|
-
if (this.masterProcess) {
|
|
459
|
-
try {
|
|
460
|
-
this.masterProcess.kill('SIGTERM');
|
|
461
|
-
await this.waitForProcessExit(this.masterProcess, this.options.gracefulTimeout);
|
|
462
|
-
}
|
|
463
|
-
catch (error) {
|
|
464
|
-
this.masterProcess.kill('SIGKILL');
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
// Stop workers
|
|
468
|
-
const shutdownPromises = [];
|
|
469
|
-
for (const [workerId, workerInfo] of this.workers.entries()) {
|
|
470
|
-
shutdownPromises.push((async () => {
|
|
471
|
-
try {
|
|
472
|
-
workerInfo.process.kill('SIGTERM');
|
|
473
|
-
await this.waitForProcessExit(workerInfo.process, this.options.gracefulTimeout);
|
|
474
|
-
}
|
|
475
|
-
catch (error) {
|
|
476
|
-
workerInfo.process.kill('SIGKILL');
|
|
477
|
-
}
|
|
478
|
-
})());
|
|
479
|
-
}
|
|
480
|
-
await Promise.allSettled(shutdownPromises);
|
|
481
|
-
this.workers.clear();
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
exports.StartManager = StartManager;
|
package/dist/src/types.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
export interface RunOptions {
|
|
2
|
-
parallel: boolean;
|
|
3
|
-
maxParallel?: number;
|
|
4
|
-
printOutput: boolean;
|
|
5
|
-
color: boolean;
|
|
6
|
-
showTiming: boolean;
|
|
7
|
-
prefix: boolean;
|
|
8
|
-
stopOnError: boolean;
|
|
9
|
-
minimalOutput: boolean;
|
|
10
|
-
groupOutput: boolean;
|
|
11
|
-
isServerMode: boolean;
|
|
12
|
-
retry?: number;
|
|
13
|
-
retryDelay?: number;
|
|
14
|
-
}
|
|
15
|
-
export interface RunResult {
|
|
16
|
-
stderr: any;
|
|
17
|
-
command: string;
|
|
18
|
-
success: boolean;
|
|
19
|
-
code: number | null;
|
|
20
|
-
startTime: Date;
|
|
21
|
-
endTime: Date | null;
|
|
22
|
-
duration?: number;
|
|
23
|
-
error?: Error;
|
|
24
|
-
output?: CommandOutput[];
|
|
25
|
-
}
|
|
26
|
-
export interface CommandOutput {
|
|
27
|
-
command: string;
|
|
28
|
-
type: 'stdout' | 'stderr';
|
|
29
|
-
data: string;
|
|
30
|
-
timestamp: Date;
|
|
31
|
-
}
|
|
32
|
-
export interface ServerInfo {
|
|
33
|
-
name: string;
|
|
34
|
-
url?: string;
|
|
35
|
-
status: 'starting' | 'running' | 'error' | 'stopped';
|
|
36
|
-
pid?: number;
|
|
37
|
-
port?: number;
|
|
38
|
-
startTime?: Date;
|
|
39
|
-
}
|
|
40
|
-
export type LogLevel = 'info' | 'warn' | 'error' | 'debug' | 'success';
|
|
41
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/src/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,UAAU;IAEzB,QAAQ,EAAE,OAAO,CAAC;IAElB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,WAAW,EAAE,OAAO,CAAC;IAErB,KAAK,EAAE,OAAO,CAAC;IAEf,UAAU,EAAE,OAAO,CAAC;IAEpB,MAAM,EAAE,OAAO,CAAC;IAEhB,WAAW,EAAE,OAAO,CAAC;IAErB,aAAa,EAAE,OAAO,CAAC;IAEvB,WAAW,EAAE,OAAO,CAAC;IAErB,YAAY,EAAE,OAAO,CAAC;IAEtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,GAAG,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC"}
|
package/dist/src/types.js
DELETED
package/dist/src/utils.d.ts
DELETED
package/dist/src/utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAKjD"}
|
package/dist/src/utils.js
DELETED