neex 0.3.7 → 0.3.9
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/.env +2 -0
- package/bun.lock +29 -93
- package/dist/project-manager.js +19 -3
- package/dist/project-manager.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/package.json +5 -2
- package/bunfig.toml +0 -2
- package/dist/bin/neex.js +0 -4
- package/dist/commands/build.d.ts +0 -3
- package/dist/commands/build.js +0 -41
- package/dist/commands/build.js.map +0 -1
- package/dist/commands/cache.d.ts +0 -3
- package/dist/commands/cache.js +0 -34
- package/dist/commands/cache.js.map +0 -1
- package/dist/commands/dev.d.ts +0 -3
- package/dist/commands/dev.js +0 -51
- package/dist/commands/dev.js.map +0 -1
- package/dist/commands/process.d.ts +0 -2
- package/dist/commands/process.js +0 -216
- package/dist/commands/process.js.map +0 -1
- package/dist/commands/run.d.ts +0 -2
- package/dist/commands/run.js +0 -81
- package/dist/commands/run.js.map +0 -1
- package/dist/commands/start.d.ts +0 -3
- package/dist/commands/start.js +0 -45
- package/dist/commands/start.js.map +0 -1
- package/dist/dev-manager.d.ts +0 -35
- package/dist/dev-manager.js +0 -172
- package/dist/dev-manager.js.map +0 -1
- package/dist/src/cli.js +0 -519
- package/dist/src/index.js +0 -70
- package/dist/src/logger.js +0 -237
- package/dist/src/process-manager.js +0 -258
- package/dist/src/runner.js +0 -320
- package/dist/src/types.js +0 -2
package/dist/src/logger.js
DELETED
|
@@ -1,237 +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
|
-
// src/logger.ts
|
|
7
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
-
const figures_1 = __importDefault(require("figures"));
|
|
9
|
-
const string_width_1 = __importDefault(require("string-width"));
|
|
10
|
-
class Logger {
|
|
11
|
-
constructor() {
|
|
12
|
-
this.prefixLength = 0;
|
|
13
|
-
this.outputBuffer = new Map();
|
|
14
|
-
this.commandColors = new Map();
|
|
15
|
-
this.startTimes = new Map();
|
|
16
|
-
this.spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
17
|
-
this.spinnerIndex = 0;
|
|
18
|
-
this.spinnerIntervals = new Map();
|
|
19
|
-
this.isSpinnerActive = false;
|
|
20
|
-
}
|
|
21
|
-
static getInstance() {
|
|
22
|
-
if (!Logger.instance) {
|
|
23
|
-
Logger.instance = new Logger();
|
|
24
|
-
}
|
|
25
|
-
return Logger.instance;
|
|
26
|
-
}
|
|
27
|
-
getSpinnerFrame() {
|
|
28
|
-
const frame = this.spinnerFrames[this.spinnerIndex];
|
|
29
|
-
this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
|
|
30
|
-
return frame;
|
|
31
|
-
}
|
|
32
|
-
showBanner() {
|
|
33
|
-
console.log('\n' + chalk_1.default.bgHex('#0066FF').black(' Neex ') + '\n');
|
|
34
|
-
}
|
|
35
|
-
setCommands(commands) {
|
|
36
|
-
// Clear any existing spinner intervals
|
|
37
|
-
this.stopAllSpinners();
|
|
38
|
-
// Show Neex banner
|
|
39
|
-
this.showBanner();
|
|
40
|
-
// Calculate prefix length for aligning output
|
|
41
|
-
this.prefixLength = Math.max(...commands.map(cmd => (0, string_width_1.default)(cmd))) + 3;
|
|
42
|
-
// Initialize buffers and colors for each command
|
|
43
|
-
commands.forEach(cmd => {
|
|
44
|
-
this.outputBuffer.set(cmd, []);
|
|
45
|
-
this.commandColors.set(cmd, this.generateColor(cmd));
|
|
46
|
-
});
|
|
47
|
-
// Log commands that will be executed
|
|
48
|
-
console.log(chalk_1.default.dim('» Commands to execute:'));
|
|
49
|
-
commands.forEach(cmd => {
|
|
50
|
-
const color = this.commandColors.get(cmd) || chalk_1.default.white;
|
|
51
|
-
console.log(chalk_1.default.dim(' ┌') + color(` ${cmd}`));
|
|
52
|
-
});
|
|
53
|
-
console.log(''); // Add a blank line after commands list
|
|
54
|
-
}
|
|
55
|
-
generateColor(command) {
|
|
56
|
-
// Generate distinct colors for commands based on the command string
|
|
57
|
-
const vibrantColors = [
|
|
58
|
-
'#00BFFF',
|
|
59
|
-
'#32CD32',
|
|
60
|
-
'#FF6347',
|
|
61
|
-
'#9370DB',
|
|
62
|
-
'#FF8C00',
|
|
63
|
-
'#20B2AA',
|
|
64
|
-
'#0066FF',
|
|
65
|
-
'#4169E1',
|
|
66
|
-
'#FFD700',
|
|
67
|
-
'#8A2BE2' // Blue Violet
|
|
68
|
-
];
|
|
69
|
-
let hash = 0;
|
|
70
|
-
for (let i = 0; i < command.length; i++) {
|
|
71
|
-
hash = (hash << 5) - hash + command.charCodeAt(i);
|
|
72
|
-
hash |= 0; // Convert to 32bit integer
|
|
73
|
-
}
|
|
74
|
-
const colorIndex = Math.abs(hash) % vibrantColors.length;
|
|
75
|
-
return chalk_1.default.hex(vibrantColors[colorIndex]);
|
|
76
|
-
}
|
|
77
|
-
formatPrefix(command) {
|
|
78
|
-
const color = this.commandColors.get(command) || chalk_1.default.white;
|
|
79
|
-
const prefix = `${command}:`.padEnd(this.prefixLength);
|
|
80
|
-
return color(prefix);
|
|
81
|
-
}
|
|
82
|
-
bufferOutput(output) {
|
|
83
|
-
const currentBuffer = this.outputBuffer.get(output.command) || [];
|
|
84
|
-
currentBuffer.push(output);
|
|
85
|
-
this.outputBuffer.set(output.command, currentBuffer);
|
|
86
|
-
}
|
|
87
|
-
printBuffer(command) {
|
|
88
|
-
const buffer = this.outputBuffer.get(command) || [];
|
|
89
|
-
const color = this.commandColors.get(command) || chalk_1.default.white;
|
|
90
|
-
// Stop spinner for this command if running
|
|
91
|
-
this.stopSpinner(command);
|
|
92
|
-
buffer.forEach(output => {
|
|
93
|
-
const prefix = this.formatPrefix(output.command);
|
|
94
|
-
const content = output.data.trim();
|
|
95
|
-
if (content) {
|
|
96
|
-
const lines = content.split('\n');
|
|
97
|
-
lines.forEach(line => {
|
|
98
|
-
if (line.trim()) {
|
|
99
|
-
const outputLine = `${prefix} ${line}`;
|
|
100
|
-
// Show stderr in appropriate colors
|
|
101
|
-
if (output.type === 'stderr') {
|
|
102
|
-
// Not all stderr is an error, check for warning or info patterns
|
|
103
|
-
if (line.toLowerCase().includes('warn') || line.toLowerCase().includes('warning')) {
|
|
104
|
-
console.log(`${prefix} ${chalk_1.default.yellow(line)}`);
|
|
105
|
-
}
|
|
106
|
-
else if (line.toLowerCase().includes('error')) {
|
|
107
|
-
console.log(`${prefix} ${chalk_1.default.red(line)}`);
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
console.log(`${prefix} ${line}`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
console.log(outputLine);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
// Clear buffer after printing
|
|
121
|
-
this.outputBuffer.set(command, []);
|
|
122
|
-
}
|
|
123
|
-
printLine(message, level = 'info') {
|
|
124
|
-
if (level === 'error') {
|
|
125
|
-
console.error(chalk_1.default.red(`${figures_1.default.cross} ${message}`));
|
|
126
|
-
}
|
|
127
|
-
else if (level === 'warn') {
|
|
128
|
-
console.warn(chalk_1.default.yellow(`${figures_1.default.warning} ${message}`));
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
console.log(chalk_1.default.blue(`${figures_1.default.info} ${message}`));
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
printStart(command) {
|
|
135
|
-
// Record start time
|
|
136
|
-
this.startTimes.set(command, new Date());
|
|
137
|
-
const prefix = this.formatPrefix(command);
|
|
138
|
-
const color = this.commandColors.get(command) || chalk_1.default.white;
|
|
139
|
-
console.log(`${prefix} ${color('Starting...')}`);
|
|
140
|
-
// Start spinner for this command
|
|
141
|
-
this.startSpinner(command);
|
|
142
|
-
}
|
|
143
|
-
startSpinner(command) {
|
|
144
|
-
// Only create a spinner if one doesn't already exist for this command
|
|
145
|
-
if (this.spinnerIntervals.has(command)) {
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
this.isSpinnerActive = true;
|
|
149
|
-
const color = this.commandColors.get(command) || chalk_1.default.white;
|
|
150
|
-
const prefix = this.formatPrefix(command);
|
|
151
|
-
const interval = setInterval(() => {
|
|
152
|
-
const frame = this.getSpinnerFrame();
|
|
153
|
-
process.stdout.write(`\r${prefix} ${color(frame)} ${chalk_1.default.dim('Running...')}`);
|
|
154
|
-
}, 80);
|
|
155
|
-
this.spinnerIntervals.set(command, interval);
|
|
156
|
-
}
|
|
157
|
-
stopSpinner(command) {
|
|
158
|
-
const interval = this.spinnerIntervals.get(command);
|
|
159
|
-
if (interval) {
|
|
160
|
-
clearInterval(interval);
|
|
161
|
-
this.spinnerIntervals.delete(command);
|
|
162
|
-
// Clear the spinner line
|
|
163
|
-
if (this.isSpinnerActive) {
|
|
164
|
-
process.stdout.write('\r' + ' '.repeat(process.stdout.columns || 80) + '\r');
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
stopAllSpinners() {
|
|
169
|
-
this.spinnerIntervals.forEach((interval, command) => {
|
|
170
|
-
clearInterval(interval);
|
|
171
|
-
});
|
|
172
|
-
this.spinnerIntervals.clear();
|
|
173
|
-
this.isSpinnerActive = false;
|
|
174
|
-
// Clear the spinner line if any spinner was active
|
|
175
|
-
if (this.isSpinnerActive) {
|
|
176
|
-
process.stdout.write('\r' + ' '.repeat(process.stdout.columns || 80) + '\r');
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
printSuccess(result) {
|
|
180
|
-
const { command, duration } = result;
|
|
181
|
-
this.stopSpinner(command);
|
|
182
|
-
const prefix = this.formatPrefix(command);
|
|
183
|
-
const color = this.commandColors.get(command) || chalk_1.default.white;
|
|
184
|
-
const durationStr = duration
|
|
185
|
-
? ` ${chalk_1.default.dim(`(${(duration / 1000).toFixed(2)}s)`)}`
|
|
186
|
-
: '';
|
|
187
|
-
console.log(`${prefix} ${chalk_1.default.green(figures_1.default.tick)} ${chalk_1.default.green('Completed')}${durationStr}`);
|
|
188
|
-
}
|
|
189
|
-
printError(result) {
|
|
190
|
-
const { command, error, code, duration } = result;
|
|
191
|
-
this.stopSpinner(command);
|
|
192
|
-
const prefix = this.formatPrefix(command);
|
|
193
|
-
const durationStr = duration ? ` ${chalk_1.default.dim(`(${(duration / 1000).toFixed(2)}s)`)}` : '';
|
|
194
|
-
const errorCode = code !== null ? ` ${chalk_1.default.red(`[code: ${code}]`)}` : '';
|
|
195
|
-
console.error(`${prefix} ${chalk_1.default.red(figures_1.default.cross)} ${chalk_1.default.red('Failed')}${errorCode}${durationStr}`);
|
|
196
|
-
if (error) {
|
|
197
|
-
console.error(`${prefix} ${chalk_1.default.red(error.message)}`);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
printSummary(results) {
|
|
201
|
-
// Stop any remaining spinners
|
|
202
|
-
this.stopAllSpinners();
|
|
203
|
-
const successful = results.filter(r => r.success).length;
|
|
204
|
-
const failed = results.length - successful;
|
|
205
|
-
const totalDuration = results.reduce((sum, result) => sum + (result.duration || 0), 0);
|
|
206
|
-
const totalSeconds = (totalDuration / 1000).toFixed(2);
|
|
207
|
-
console.log('\n' + chalk_1.default.bgHex('#0066FF').black(' Execution Summary ') + '\n');
|
|
208
|
-
console.log(`${chalk_1.default.green(`${figures_1.default.tick} ${successful} succeeded`)}, ${chalk_1.default.red(`${figures_1.default.cross} ${failed} failed`)}`);
|
|
209
|
-
console.log(`${chalk_1.default.blue(figures_1.default.info)} ${chalk_1.default.dim(`Total execution time: ${totalSeconds}s`)}`);
|
|
210
|
-
if (successful > 0) {
|
|
211
|
-
console.log('\n' + chalk_1.default.green.bold('Successful commands:'));
|
|
212
|
-
results
|
|
213
|
-
.filter(r => r.success)
|
|
214
|
-
.forEach(result => {
|
|
215
|
-
const color = this.commandColors.get(result.command) || chalk_1.default.white;
|
|
216
|
-
const duration = result.duration
|
|
217
|
-
? chalk_1.default.dim(` (${(result.duration / 1000).toFixed(2)}s)`)
|
|
218
|
-
: '';
|
|
219
|
-
console.log(` ${chalk_1.default.green(figures_1.default.tick)} ${color(result.command)}${duration}`);
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
if (failed > 0) {
|
|
223
|
-
console.log('\n' + chalk_1.default.red.bold('Failed commands:'));
|
|
224
|
-
results
|
|
225
|
-
.filter(r => !r.success)
|
|
226
|
-
.forEach(result => {
|
|
227
|
-
const color = this.commandColors.get(result.command) || chalk_1.default.white;
|
|
228
|
-
const duration = result.duration
|
|
229
|
-
? chalk_1.default.dim(` (${(result.duration / 1000).toFixed(2)}s)`)
|
|
230
|
-
: '';
|
|
231
|
-
const code = result.code !== null ? chalk_1.default.red(` [code: ${result.code}]`) : '';
|
|
232
|
-
console.log(` ${chalk_1.default.red(figures_1.default.cross)} ${color(result.command)}${code}${duration}`);
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
exports.default = Logger.getInstance();
|
|
@@ -1,258 +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.processManager = void 0;
|
|
7
|
-
const child_process_1 = require("child_process");
|
|
8
|
-
const chokidar_1 = require("chokidar");
|
|
9
|
-
const fs_1 = require("fs");
|
|
10
|
-
const path_1 = require("path");
|
|
11
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
-
const events_1 = require("events");
|
|
13
|
-
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
14
|
-
const child_process_2 = require("child_process");
|
|
15
|
-
class ProcessManager extends events_1.EventEmitter {
|
|
16
|
-
constructor() {
|
|
17
|
-
super();
|
|
18
|
-
this.processes = new Map();
|
|
19
|
-
this.watchers = new Map();
|
|
20
|
-
this.defaultMaxRestarts = 5;
|
|
21
|
-
this.defaultRestartDelay = 1000;
|
|
22
|
-
this.logDir = (0, path_1.resolve)(process.cwd(), '.neex-logs');
|
|
23
|
-
this.configFile = (0, path_1.resolve)(process.cwd(), '.neex-config.json');
|
|
24
|
-
this.initialize();
|
|
25
|
-
}
|
|
26
|
-
initialize() {
|
|
27
|
-
if (!(0, fs_1.existsSync)(this.logDir)) {
|
|
28
|
-
(0, fs_1.mkdirSync)(this.logDir, { recursive: true });
|
|
29
|
-
}
|
|
30
|
-
this.loadConfig();
|
|
31
|
-
}
|
|
32
|
-
loadConfig() {
|
|
33
|
-
if ((0, fs_1.existsSync)(this.configFile)) {
|
|
34
|
-
const config = JSON.parse((0, fs_1.readFileSync)(this.configFile, 'utf-8'));
|
|
35
|
-
this.processes = new Map(Object.entries(config));
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
saveConfig() {
|
|
39
|
-
const config = Object.fromEntries(this.processes);
|
|
40
|
-
(0, fs_1.writeFileSync)(this.configFile, JSON.stringify(config, null, 2));
|
|
41
|
-
}
|
|
42
|
-
generateName(command) {
|
|
43
|
-
const baseName = command.split(' ')[0].replace(/[^a-zA-Z0-9]/g, '');
|
|
44
|
-
const timestamp = Date.now().toString(36);
|
|
45
|
-
return `${baseName}-${timestamp}`;
|
|
46
|
-
}
|
|
47
|
-
getLogPath(name) {
|
|
48
|
-
return (0, path_1.join)(this.logDir, `${name}.log`);
|
|
49
|
-
}
|
|
50
|
-
async startx(command, options = {}) {
|
|
51
|
-
const name = options.name || this.generateName(command);
|
|
52
|
-
const cwd = options.cwd || process.cwd();
|
|
53
|
-
if (this.processes.has(name)) {
|
|
54
|
-
throw new Error(`Process with name ${name} already exists`);
|
|
55
|
-
}
|
|
56
|
-
const processInfo = {
|
|
57
|
-
name,
|
|
58
|
-
pid: 0,
|
|
59
|
-
status: 'stopped',
|
|
60
|
-
startTime: Date.now(),
|
|
61
|
-
command,
|
|
62
|
-
logs: [],
|
|
63
|
-
memory: 0,
|
|
64
|
-
cpu: 0,
|
|
65
|
-
uptime: 0,
|
|
66
|
-
restarts: 0,
|
|
67
|
-
maxRestarts: options.maxRestarts || this.defaultMaxRestarts,
|
|
68
|
-
restartDelay: options.restartDelay || this.defaultRestartDelay,
|
|
69
|
-
watch: options.watch,
|
|
70
|
-
cwd
|
|
71
|
-
};
|
|
72
|
-
try {
|
|
73
|
-
await this.startProcess(processInfo);
|
|
74
|
-
return processInfo;
|
|
75
|
-
}
|
|
76
|
-
catch (error) {
|
|
77
|
-
processInfo.status = 'error';
|
|
78
|
-
processInfo.lastError = error.message;
|
|
79
|
-
this.processes.set(name, processInfo);
|
|
80
|
-
this.saveConfig();
|
|
81
|
-
throw error;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
async startProcess(processInfo) {
|
|
85
|
-
var _a, _b;
|
|
86
|
-
const [cmd, ...args] = processInfo.command.split(' ');
|
|
87
|
-
const child = (0, child_process_1.spawn)(cmd, args, {
|
|
88
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
89
|
-
env: { ...process.env, NODE_ENV: 'production' },
|
|
90
|
-
cwd: processInfo.cwd,
|
|
91
|
-
shell: true
|
|
92
|
-
});
|
|
93
|
-
processInfo.pid = child.pid || 0;
|
|
94
|
-
processInfo.status = 'running';
|
|
95
|
-
processInfo.startTime = Date.now();
|
|
96
|
-
// Setup logging
|
|
97
|
-
(0, fs_1.writeFileSync)(this.getLogPath(processInfo.name), '', { flag: 'a' });
|
|
98
|
-
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
|
|
99
|
-
const log = data.toString();
|
|
100
|
-
processInfo.logs.push(log);
|
|
101
|
-
(0, fs_1.writeFileSync)(this.getLogPath(processInfo.name), log, { flag: 'a' });
|
|
102
|
-
this.emit('log', { name: processInfo.name, log });
|
|
103
|
-
});
|
|
104
|
-
(_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
|
|
105
|
-
const log = data.toString();
|
|
106
|
-
processInfo.logs.push(log);
|
|
107
|
-
(0, fs_1.writeFileSync)(this.getLogPath(processInfo.name), log, { flag: 'a' });
|
|
108
|
-
this.emit('error', { name: processInfo.name, log });
|
|
109
|
-
});
|
|
110
|
-
// Setup monitoring
|
|
111
|
-
if (processInfo.watch && processInfo.cwd) {
|
|
112
|
-
const watcher = (0, chokidar_1.watch)(processInfo.cwd, {
|
|
113
|
-
ignored: /(^|[\/\\])\../,
|
|
114
|
-
persistent: true
|
|
115
|
-
});
|
|
116
|
-
watcher.on('change', () => {
|
|
117
|
-
this.restart(processInfo.name);
|
|
118
|
-
});
|
|
119
|
-
this.watchers.set(processInfo.name, watcher);
|
|
120
|
-
}
|
|
121
|
-
// Monitor process
|
|
122
|
-
const monitorInterval = setInterval(() => {
|
|
123
|
-
if (child.pid) {
|
|
124
|
-
try {
|
|
125
|
-
const stats = this.getProcessStats(child.pid);
|
|
126
|
-
processInfo.memory = stats.memory;
|
|
127
|
-
processInfo.cpu = stats.cpu;
|
|
128
|
-
processInfo.uptime = (Date.now() - processInfo.startTime) / 1000;
|
|
129
|
-
this.emit('stats', { name: processInfo.name, stats: processInfo });
|
|
130
|
-
}
|
|
131
|
-
catch (error) {
|
|
132
|
-
console.error(`Error monitoring process ${processInfo.name}:`, error);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}, 1000);
|
|
136
|
-
child.on('exit', async (code) => {
|
|
137
|
-
clearInterval(monitorInterval);
|
|
138
|
-
if (code !== 0) {
|
|
139
|
-
processInfo.status = 'error';
|
|
140
|
-
processInfo.lastError = `Process exited with code ${code}`;
|
|
141
|
-
this.emit('error', { name: processInfo.name, code });
|
|
142
|
-
if (processInfo.restarts < processInfo.maxRestarts) {
|
|
143
|
-
processInfo.status = 'restarting';
|
|
144
|
-
this.emit('restart', { name: processInfo.name, attempt: processInfo.restarts + 1 });
|
|
145
|
-
await new Promise(resolve => setTimeout(resolve, processInfo.restartDelay));
|
|
146
|
-
processInfo.restarts++;
|
|
147
|
-
await this.startProcess(processInfo);
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
this.emit('max-restarts', { name: processInfo.name, maxRestarts: processInfo.maxRestarts });
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
processInfo.status = 'stopped';
|
|
155
|
-
}
|
|
156
|
-
this.saveConfig();
|
|
157
|
-
});
|
|
158
|
-
this.processes.set(processInfo.name, processInfo);
|
|
159
|
-
this.saveConfig();
|
|
160
|
-
this.emit('start', { name: processInfo.name, processInfo });
|
|
161
|
-
}
|
|
162
|
-
getProcessStats(pid) {
|
|
163
|
-
try {
|
|
164
|
-
const stats = (0, child_process_2.execSync)(`ps -p ${pid} -o %mem,%cpu`).toString().split('\n')[1].trim().split(/\s+/);
|
|
165
|
-
return {
|
|
166
|
-
memory: parseFloat(stats[0]),
|
|
167
|
-
cpu: parseFloat(stats[1])
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
catch (_a) {
|
|
171
|
-
return { memory: 0, cpu: 0 };
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
async stopx(name) {
|
|
175
|
-
const processInfo = this.processes.get(name);
|
|
176
|
-
if (!processInfo) {
|
|
177
|
-
throw new Error(`Process ${name} not found`);
|
|
178
|
-
}
|
|
179
|
-
try {
|
|
180
|
-
process.kill(processInfo.pid);
|
|
181
|
-
const watcher = this.watchers.get(name);
|
|
182
|
-
if (watcher) {
|
|
183
|
-
watcher.close();
|
|
184
|
-
this.watchers.delete(name);
|
|
185
|
-
}
|
|
186
|
-
this.processes.delete(name);
|
|
187
|
-
this.saveConfig();
|
|
188
|
-
this.emit('stop', { name });
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
throw new Error(`Failed to stop process ${name}: ${error.message}`);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
list() {
|
|
195
|
-
const table = new cli_table3_1.default({
|
|
196
|
-
head: ['Name', 'Status', 'PID', 'Memory', 'CPU', 'Uptime', 'Restarts'],
|
|
197
|
-
style: { head: ['cyan'] }
|
|
198
|
-
});
|
|
199
|
-
Array.from(this.processes.values()).forEach(process => {
|
|
200
|
-
const statusColor = process.status === 'running' ? 'green' :
|
|
201
|
-
process.status === 'error' ? 'red' :
|
|
202
|
-
process.status === 'restarting' ? 'yellow' : 'gray';
|
|
203
|
-
table.push([
|
|
204
|
-
process.name,
|
|
205
|
-
chalk_1.default[statusColor](process.status),
|
|
206
|
-
process.pid || '-',
|
|
207
|
-
`${process.memory.toFixed(2)}MB`,
|
|
208
|
-
`${process.cpu.toFixed(1)}%`,
|
|
209
|
-
`${Math.floor(process.uptime)}s`,
|
|
210
|
-
`${process.restarts}/${process.maxRestarts}`
|
|
211
|
-
]);
|
|
212
|
-
});
|
|
213
|
-
return table.toString();
|
|
214
|
-
}
|
|
215
|
-
monit(name) {
|
|
216
|
-
const processInfo = this.processes.get(name);
|
|
217
|
-
if (!processInfo) {
|
|
218
|
-
throw new Error(`Process ${name} not found`);
|
|
219
|
-
}
|
|
220
|
-
const table = new cli_table3_1.default({
|
|
221
|
-
style: { head: ['cyan'] }
|
|
222
|
-
});
|
|
223
|
-
table.push(['Name', processInfo.name], ['Status', chalk_1.default[processInfo.status === 'running' ? 'green' : 'red'](processInfo.status)], ['PID', processInfo.pid.toString()], ['Memory', `${processInfo.memory.toFixed(2)}MB`], ['CPU', `${processInfo.cpu.toFixed(1)}%`], ['Uptime', `${Math.floor(processInfo.uptime)}s`], ['Restarts', `${processInfo.restarts}/${processInfo.maxRestarts}`]);
|
|
224
|
-
if (processInfo.lastError) {
|
|
225
|
-
table.push(['Last Error', chalk_1.default.red(processInfo.lastError)]);
|
|
226
|
-
}
|
|
227
|
-
return {
|
|
228
|
-
table: table.toString(),
|
|
229
|
-
logs: processInfo.logs.slice(-100)
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
log(name, lines = 100) {
|
|
233
|
-
const processInfo = this.processes.get(name);
|
|
234
|
-
if (!processInfo) {
|
|
235
|
-
throw new Error(`Process ${name} not found`);
|
|
236
|
-
}
|
|
237
|
-
const logPath = this.getLogPath(name);
|
|
238
|
-
if (!(0, fs_1.existsSync)(logPath)) {
|
|
239
|
-
return [];
|
|
240
|
-
}
|
|
241
|
-
const logs = (0, fs_1.readFileSync)(logPath, 'utf-8').split('\n');
|
|
242
|
-
return logs.slice(-lines);
|
|
243
|
-
}
|
|
244
|
-
async restart(name) {
|
|
245
|
-
const processInfo = this.processes.get(name);
|
|
246
|
-
if (!processInfo) {
|
|
247
|
-
throw new Error(`Process ${name} not found`);
|
|
248
|
-
}
|
|
249
|
-
await this.stopx(name);
|
|
250
|
-
processInfo.restarts++;
|
|
251
|
-
await this.startx(processInfo.command, {
|
|
252
|
-
name: processInfo.name,
|
|
253
|
-
watch: true,
|
|
254
|
-
cwd: processInfo.cwd
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
exports.processManager = new ProcessManager();
|