neex 0.7.20 → 0.7.32

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.
Files changed (58) hide show
  1. package/README.md +13 -31
  2. package/dist/bin/neex.d.ts +26 -0
  3. package/dist/bin/neex.d.ts.map +1 -0
  4. package/dist/src/build-manager.d.ts +41 -0
  5. package/dist/src/build-manager.d.ts.map +1 -0
  6. package/dist/src/build-manager.js +26 -24
  7. package/dist/src/cli.d.ts +2 -0
  8. package/dist/src/cli.d.ts.map +1 -0
  9. package/dist/src/commands/build-commands.d.ts +5 -0
  10. package/dist/src/commands/build-commands.d.ts.map +1 -0
  11. package/dist/src/commands/build-commands.js +2 -2
  12. package/dist/src/commands/dev-commands.d.ts +5 -0
  13. package/dist/src/commands/dev-commands.d.ts.map +1 -0
  14. package/dist/src/commands/dev-commands.js +5 -3
  15. package/dist/src/commands/index.d.ts +7 -0
  16. package/dist/src/commands/index.d.ts.map +1 -0
  17. package/dist/src/commands/init-commands.d.ts +2 -0
  18. package/dist/src/commands/init-commands.d.ts.map +1 -0
  19. package/dist/src/commands/init-commands.js +4 -4
  20. package/dist/src/commands/run-commands.d.ts +3 -0
  21. package/dist/src/commands/run-commands.d.ts.map +1 -0
  22. package/dist/src/commands/run-commands.js +26 -26
  23. package/dist/src/commands/server-commands.d.ts +3 -0
  24. package/dist/src/commands/server-commands.d.ts.map +1 -0
  25. package/dist/src/commands/server-commands.js +4 -2
  26. package/dist/src/commands/start-commands.d.ts +5 -0
  27. package/dist/src/commands/start-commands.d.ts.map +1 -0
  28. package/dist/src/commands/start-commands.js +2 -2
  29. package/dist/src/dev-manager.d.ts +51 -0
  30. package/dist/src/dev-manager.d.ts.map +1 -0
  31. package/dist/src/dev-manager.js +29 -21
  32. package/dist/src/index.d.ts +41 -0
  33. package/dist/src/index.d.ts.map +1 -0
  34. package/dist/src/index.js +15 -16
  35. package/dist/src/logger-manager.d.ts +4 -0
  36. package/dist/src/logger-manager.d.ts.map +1 -0
  37. package/dist/src/logger-manager.js +4 -4
  38. package/dist/src/logger.d.ts +34 -0
  39. package/dist/src/logger.d.ts.map +1 -0
  40. package/dist/src/logger.js +21 -15
  41. package/dist/src/runner.d.ts +21 -0
  42. package/dist/src/runner.d.ts.map +1 -0
  43. package/dist/src/runner.js +38 -25
  44. package/dist/src/start-manager.d.ts +49 -0
  45. package/dist/src/start-manager.d.ts.map +1 -0
  46. package/dist/src/start-manager.js +34 -29
  47. package/dist/src/types.d.ts +41 -0
  48. package/dist/src/types.d.ts.map +1 -0
  49. package/dist/src/utils.d.ts +2 -0
  50. package/dist/src/utils.d.ts.map +1 -0
  51. package/package.json +14 -9
  52. package/dist/src/cli-init.js +0 -1
  53. package/dist/src/commands/process-commands.js +0 -759
  54. package/dist/src/config.js +0 -59
  55. package/dist/src/dev-runner.js +0 -234
  56. package/dist/src/logger-process.js +0 -17
  57. package/dist/src/process-manager.js +0 -669
  58. package/dist/src/watcher.js +0 -245
@@ -1,759 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.addProcessCommands = void 0;
30
- const process_manager_js_1 = require("../process-manager.js");
31
- const chalk_1 = __importDefault(require("chalk"));
32
- const figures_1 = __importDefault(require("figures"));
33
- const path = __importStar(require("path"));
34
- const fs = __importStar(require("fs"));
35
- const fs_1 = require("fs");
36
- // Helper function to format uptime
37
- function formatUptime(seconds) {
38
- if (seconds < 60) {
39
- return `${seconds}s`;
40
- }
41
- else if (seconds < 3600) {
42
- const minutes = Math.floor(seconds / 60);
43
- const remainingSeconds = seconds % 60;
44
- return `${minutes}m ${remainingSeconds}s`;
45
- }
46
- else {
47
- const hours = Math.floor(seconds / 3600);
48
- const minutes = Math.floor((seconds % 3600) / 60);
49
- return `${hours}h ${minutes}m`;
50
- }
51
- }
52
- // Helper function to format memory
53
- function formatMemory(bytes) {
54
- if (bytes === 0)
55
- return '0B';
56
- const k = 1024;
57
- const sizes = ['B', 'KB', 'MB', 'GB'];
58
- const i = Math.floor(Math.log(bytes) / Math.log(k));
59
- return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + sizes[i];
60
- }
61
- // Helper function to format CPU
62
- function formatCpu(cpu) {
63
- return `${cpu.toFixed(1)}%`;
64
- }
65
- function addProcessCommands(program) {
66
- let processManager = null;
67
- const getOrCreateProcessManager = async () => {
68
- if (!processManager) {
69
- processManager = new process_manager_js_1.ProcessManager();
70
- await processManager.load();
71
- }
72
- return processManager;
73
- };
74
- // Start command - اجرای برنامه
75
- program
76
- .command('start <script>')
77
- .description('Start a new process')
78
- .option('-n, --name <name>', 'Process name')
79
- .option('-i, --instances <number>', 'Number of instances', parseInt)
80
- .option('--cwd <path>', 'Working directory')
81
- .option('--env <env>', 'Environment variables (JSON string)')
82
- .option('--no-autorestart', 'Disable auto-restart')
83
- .option('--max-restarts <number>', 'Maximum restarts', parseInt)
84
- .option('--restart-delay <ms>', 'Restart delay in ms', parseInt)
85
- .option('--watch', 'Enable file watching')
86
- .option('--ignore-watch <patterns...>', 'Patterns to ignore when watching')
87
- .option('--max-memory <size>', 'Max memory before restart (e.g., 1G, 500M)')
88
- .option('--interpreter <interpreter>', 'Interpreter to use (node, ts-node, etc.)')
89
- .option('--interpreter-args <args>', 'Interpreter arguments')
90
- .option('--log <path>', 'Log file path')
91
- .option('--error <path>', 'Error log file path')
92
- .option('--time', 'Prefix logs with timestamp')
93
- .option('--merge-logs', 'Merge logs and errors')
94
- .option('--typescript', 'Script is TypeScript (will use ts-node)')
95
- .option('--build-dir <dir>', 'Build directory for TypeScript projects', 'dist')
96
- .action(async (script, options) => {
97
- try {
98
- const pm = await getOrCreateProcessManager();
99
- // Resolve script path
100
- const scriptPath = path.resolve(script);
101
- if (!fs.existsSync(scriptPath)) {
102
- console.error(chalk_1.default.red(`${figures_1.default.cross} Script file not found: ${scriptPath}`));
103
- process.exit(1);
104
- }
105
- // If TypeScript flag is set, use ts-node
106
- const interpreter = options.typescript ? 'ts-node' : options.interpreter || 'node';
107
- const interpreterArgs = options.typescript ? ['--project', 'tsconfig.json'] : options.interpreterArgs ? options.interpreterArgs.split(' ') : undefined;
108
- const config = {
109
- id: '',
110
- name: options.name || path.basename(script, path.extname(script)),
111
- script: scriptPath,
112
- cwd: options.cwd ? path.resolve(options.cwd) : process.cwd(),
113
- env: options.env ? JSON.parse(options.env) : undefined,
114
- instances: options.instances || 1,
115
- autorestart: options.autorestart !== false,
116
- max_restarts: options.maxRestarts || 10,
117
- restart_delay: options.restartDelay || 1000,
118
- watch: options.watch || false,
119
- ignore_watch: options.ignoreWatch,
120
- max_memory_restart: options.maxMemory,
121
- interpreter,
122
- interpreter_args: interpreterArgs,
123
- log_file: options.log,
124
- error_file: options.error,
125
- out_file: options.log,
126
- time: options.time || false,
127
- merge_logs: options.mergeLogs || false
128
- };
129
- const id = await pm.start(config);
130
- console.log(chalk_1.default.green(`${figures_1.default.tick} Process started successfully`));
131
- console.log(chalk_1.default.blue(`${figures_1.default.info} Process ID: ${id}`));
132
- console.log(chalk_1.default.blue(`${figures_1.default.info} Process Name: ${config.name}`));
133
- console.log(chalk_1.default.blue(`${figures_1.default.info} Script: ${scriptPath}`));
134
- console.log(chalk_1.default.blue(`${figures_1.default.info} Interpreter: ${interpreter}`));
135
- }
136
- catch (error) {
137
- if (error instanceof Error) {
138
- console.error(chalk_1.default.red(`${figures_1.default.cross} Start Error: ${error.message}`));
139
- }
140
- else {
141
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown start error occurred`));
142
- }
143
- process.exit(1);
144
- }
145
- });
146
- // Stop command - توقف برنامه
147
- program
148
- .command('stop <id>')
149
- .description('Stop a process (use "all" to stop all processes)')
150
- .action(async (id) => {
151
- try {
152
- const pm = await getOrCreateProcessManager();
153
- if (id === 'all') {
154
- await pm.stopAll();
155
- console.log(chalk_1.default.green(`${figures_1.default.tick} All processes stopped`));
156
- }
157
- else {
158
- await pm.stop(id);
159
- console.log(chalk_1.default.green(`${figures_1.default.tick} Process ${id} stopped`));
160
- }
161
- }
162
- catch (error) {
163
- if (error instanceof Error) {
164
- console.error(chalk_1.default.red(`${figures_1.default.cross} Stop Error: ${error.message}`));
165
- }
166
- else {
167
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown stop error occurred`));
168
- }
169
- process.exit(1);
170
- }
171
- });
172
- // Restart command - راه‌اندازی مجدد
173
- program
174
- .command('restart <id>')
175
- .description('Restart a process (use "all" to restart all processes)')
176
- .action(async (id) => {
177
- try {
178
- const pm = await getOrCreateProcessManager();
179
- if (id === 'all') {
180
- await pm.restartAll();
181
- console.log(chalk_1.default.green(`${figures_1.default.tick} All processes restarted`));
182
- }
183
- else {
184
- await pm.restart(id);
185
- console.log(chalk_1.default.green(`${figures_1.default.tick} Process ${id} restarted`));
186
- }
187
- }
188
- catch (error) {
189
- if (error instanceof Error) {
190
- console.error(chalk_1.default.red(`${figures_1.default.cross} Restart Error: ${error.message}`));
191
- }
192
- else {
193
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown restart error occurred`));
194
- }
195
- process.exit(1);
196
- }
197
- });
198
- // Delete command - حذف برنامه
199
- program
200
- .command('delete <id>')
201
- .alias('del')
202
- .description('Delete a process (use "all" to delete all processes)')
203
- .action(async (id) => {
204
- try {
205
- const pm = await getOrCreateProcessManager();
206
- if (id === 'all') {
207
- await pm.deleteAll();
208
- console.log(chalk_1.default.green(`${figures_1.default.tick} All processes deleted`));
209
- }
210
- else {
211
- await pm.delete(id);
212
- console.log(chalk_1.default.green(`${figures_1.default.tick} Process ${id} deleted`));
213
- }
214
- }
215
- catch (error) {
216
- if (error instanceof Error) {
217
- console.error(chalk_1.default.red(`${figures_1.default.cross} Delete Error: ${error.message}`));
218
- }
219
- else {
220
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown delete error occurred`));
221
- }
222
- process.exit(1);
223
- }
224
- });
225
- // List/Status command - نمایش وضعیت
226
- program
227
- .command('list')
228
- .alias('status')
229
- .alias('ls')
230
- .description('List all processes with detailed information')
231
- .action(async () => {
232
- try {
233
- const pm = await getOrCreateProcessManager();
234
- const processes = await pm.list();
235
- if (processes.length === 0) {
236
- console.log(chalk_1.default.yellow(`${figures_1.default.info} No processes found`));
237
- console.log(chalk_1.default.blue(`${figures_1.default.info} Use 'neex start <script>' to start a new process`));
238
- return;
239
- }
240
- // Print enhanced table
241
- console.log('\n' + chalk_1.default.bold.cyan('Neex Process Monitor'));
242
- console.log(chalk_1.default.gray('─'.repeat(100)));
243
- const header = `${chalk_1.default.bold('ID'.padEnd(12))} ${chalk_1.default.bold('Name'.padEnd(15))} ${chalk_1.default.bold('Status'.padEnd(10))} ${chalk_1.default.bold('PID'.padEnd(8))} ${chalk_1.default.bold('Uptime'.padEnd(10))} ${chalk_1.default.bold('Restarts'.padEnd(8))} ${chalk_1.default.bold('CPU'.padEnd(8))} ${chalk_1.default.bold('Memory'.padEnd(10))}`;
244
- console.log(header);
245
- console.log(chalk_1.default.gray('─'.repeat(100)));
246
- // Print process information
247
- processes.forEach(proc => {
248
- const statusColor = proc.status === 'online' ? chalk_1.default.green :
249
- proc.status === 'stopped' ? chalk_1.default.gray :
250
- proc.status === 'errored' ? chalk_1.default.red :
251
- proc.status === 'launching' ? chalk_1.default.yellow : chalk_1.default.blue;
252
- const uptime = formatUptime(proc.uptime);
253
- const pid = proc.pid ? proc.pid.toString() : 'N/A';
254
- const cpu = proc.status === 'online' ? formatCpu(proc.cpu) : 'N/A';
255
- const memory = proc.status === 'online' ? formatMemory(proc.memory) : 'N/A';
256
- const row = `${proc.id.padEnd(12)} ${proc.name.padEnd(15)} ${statusColor(proc.status.padEnd(10))} ${pid.padEnd(8)} ${uptime.padEnd(10)} ${proc.restarts.toString().padEnd(8)} ${cpu.padEnd(8)} ${memory.padEnd(10)}`;
257
- console.log(row);
258
- });
259
- console.log(chalk_1.default.gray('─'.repeat(100)));
260
- const online = processes.filter(p => p.status === 'online').length;
261
- const stopped = processes.filter(p => p.status === 'stopped').length;
262
- const errored = processes.filter(p => p.status === 'errored').length;
263
- console.log(`\n${chalk_1.default.blue(`${figures_1.default.info} Total: ${processes.length} processes`)} | ${chalk_1.default.green(`Online: ${online}`)} | ${chalk_1.default.gray(`Stopped: ${stopped}`)} | ${chalk_1.default.red(`Errored: ${errored}`)}`);
264
- }
265
- catch (error) {
266
- if (error instanceof Error) {
267
- console.error(chalk_1.default.red(`${figures_1.default.cross} List Error: ${error.message}`));
268
- }
269
- else {
270
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown list error occurred`));
271
- }
272
- process.exit(1);
273
- }
274
- });
275
- // Logs command - نمایش لاگ‌ها
276
- program
277
- .command('logs <id>')
278
- .alias('log')
279
- .description('Show process logs')
280
- .option('-l, --lines <number>', 'Number of lines to show', parseInt, 15)
281
- .option('-f, --follow', 'Follow log output')
282
- .action(async (id, options) => {
283
- try {
284
- const pm = await getOrCreateProcessManager();
285
- const processInfo = pm.getProcess(id);
286
- if (!processInfo) {
287
- console.error(chalk_1.default.red(`${figures_1.default.cross} Process ${id} not found`));
288
- process.exit(1);
289
- }
290
- console.log(chalk_1.default.blue(`${figures_1.default.info} Showing logs for process: ${processInfo.name} (${id})`));
291
- console.log(chalk_1.default.gray('─'.repeat(60)));
292
- if (options.follow) {
293
- // Follow logs
294
- const logFollower = pm.followLogs(id, (logLine) => {
295
- console.log(logLine);
296
- });
297
- if (!logFollower) {
298
- console.error(chalk_1.default.red(`${figures_1.default.cross} Failed to follow logs for process ${id}`));
299
- process.exit(1);
300
- }
301
- // Handle Ctrl+C to stop following
302
- process.on('SIGINT', () => {
303
- console.log(chalk_1.default.yellow(`\n${figures_1.default.info} Stopping log follow...`));
304
- logFollower.stop();
305
- process.exit(0);
306
- });
307
- console.log(chalk_1.default.green(`${figures_1.default.tick} Following logs... Press Ctrl+C to stop`));
308
- }
309
- else {
310
- // Show recent logs
311
- const logs = await pm.logs(id, options.lines);
312
- if (logs.length === 0) {
313
- console.log(chalk_1.default.yellow(`${figures_1.default.info} No logs found for process ${id}`));
314
- }
315
- else {
316
- logs.forEach(log => console.log(log));
317
- }
318
- }
319
- }
320
- catch (error) {
321
- if (error instanceof Error) {
322
- console.error(chalk_1.default.red(`${figures_1.default.cross} Logs Error: ${error.message}`));
323
- }
324
- else {
325
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown logs error occurred`));
326
- }
327
- process.exit(1);
328
- }
329
- });
330
- // Save command - ذخیره وضعیت
331
- program
332
- .command('save')
333
- .description('Save current process configuration')
334
- .action(async () => {
335
- try {
336
- const pm = await getOrCreateProcessManager();
337
- await pm.save();
338
- console.log(chalk_1.default.green(`${figures_1.default.tick} Process configuration saved successfully`));
339
- }
340
- catch (error) {
341
- if (error instanceof Error) {
342
- console.error(chalk_1.default.red(`${figures_1.default.cross} Save Error: ${error.message}`));
343
- }
344
- else {
345
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown save error occurred`));
346
- }
347
- process.exit(1);
348
- }
349
- });
350
- // Resurrect command - بازیابی برنامه‌ها
351
- program
352
- .command('resurrect')
353
- .description('Resurrect previously saved processes')
354
- .action(async () => {
355
- try {
356
- const pm = await getOrCreateProcessManager();
357
- await pm.load();
358
- const processes = await pm.list();
359
- const stoppedProcesses = processes.filter(p => p.status === 'stopped');
360
- if (stoppedProcesses.length === 0) {
361
- console.log(chalk_1.default.yellow(`${figures_1.default.info} No stopped processes to resurrect`));
362
- return;
363
- }
364
- console.log(chalk_1.default.blue(`${figures_1.default.info} Resurrecting ${stoppedProcesses.length} processes...`));
365
- for (const proc of stoppedProcesses) {
366
- try {
367
- await pm.restart(proc.id);
368
- console.log(chalk_1.default.green(`${figures_1.default.tick} Resurrected: ${proc.name} (${proc.id})`));
369
- }
370
- catch (error) {
371
- console.log(chalk_1.default.red(`${figures_1.default.cross} Failed to resurrect: ${proc.name} (${proc.id})`));
372
- }
373
- }
374
- }
375
- catch (error) {
376
- if (error instanceof Error) {
377
- console.error(chalk_1.default.red(`${figures_1.default.cross} Resurrect Error: ${error.message}`));
378
- }
379
- else {
380
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown resurrect error occurred`));
381
- }
382
- process.exit(1);
383
- }
384
- });
385
- // Info command - اطلاعات دقیق برنامه
386
- program
387
- .command('info <id>')
388
- .alias('show')
389
- .description('Show detailed information about a process')
390
- .action(async (id) => {
391
- try {
392
- const pm = await getOrCreateProcessManager();
393
- const processInfo = pm.getProcess(id);
394
- if (!processInfo) {
395
- console.error(chalk_1.default.red(`${figures_1.default.cross} Process ${id} not found`));
396
- process.exit(1);
397
- }
398
- console.log('\n' + chalk_1.default.bold.cyan(`Process Information: ${processInfo.name}`));
399
- console.log(chalk_1.default.gray('─'.repeat(50)));
400
- console.log(`${chalk_1.default.bold('ID:')} ${processInfo.id}`);
401
- console.log(`${chalk_1.default.bold('Name:')} ${processInfo.name}`);
402
- console.log(`${chalk_1.default.bold('Status:')} ${processInfo.status === 'online' ? chalk_1.default.green(processInfo.status) : chalk_1.default.red(processInfo.status)}`);
403
- console.log(`${chalk_1.default.bold('PID:')} ${processInfo.pid || 'N/A'}`);
404
- console.log(`${chalk_1.default.bold('Uptime:')} ${formatUptime(processInfo.uptime)}`);
405
- console.log(`${chalk_1.default.bold('Restarts:')} ${processInfo.restarts}`);
406
- console.log(`${chalk_1.default.bold('CPU:')} ${formatCpu(processInfo.cpu)}`);
407
- console.log(`${chalk_1.default.bold('Memory:')} ${formatMemory(processInfo.memory)}`);
408
- console.log(`${chalk_1.default.bold('Script:')} ${processInfo.config.script}`);
409
- console.log(`${chalk_1.default.bold('Working Directory:')} ${processInfo.config.cwd || process.cwd()}`);
410
- console.log(`${chalk_1.default.bold('Auto Restart:')} ${processInfo.config.autorestart ? 'Yes' : 'No'}`);
411
- console.log(`${chalk_1.default.bold('Max Restarts:')} ${processInfo.config.max_restarts}`);
412
- console.log(`${chalk_1.default.bold('Created At:')} ${processInfo.created_at.toISOString()}`);
413
- if (processInfo.started_at) {
414
- console.log(`${chalk_1.default.bold('Started At:')} ${processInfo.started_at.toISOString()}`);
415
- }
416
- if (processInfo.last_restart) {
417
- console.log(`${chalk_1.default.bold('Last Restart:')} ${processInfo.last_restart.toISOString()}`);
418
- }
419
- if (processInfo.config.env) {
420
- console.log(`${chalk_1.default.bold('Environment Variables:')}`);
421
- Object.entries(processInfo.config.env).forEach(([key, value]) => {
422
- console.log(` ${key}: ${value}`);
423
- });
424
- }
425
- }
426
- catch (error) {
427
- if (error instanceof Error) {
428
- console.error(chalk_1.default.red(`${figures_1.default.cross} Info Error: ${error.message}`));
429
- }
430
- else {
431
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown info error occurred`));
432
- }
433
- process.exit(1);
434
- }
435
- });
436
- // Monitor command - مانیتور زنده
437
- program
438
- .command('monitor')
439
- .alias('monit')
440
- .description('Launch process monitor dashboard')
441
- .action(async () => {
442
- try {
443
- const pm = await getOrCreateProcessManager();
444
- console.log(chalk_1.default.blue(`${figures_1.default.info} Starting Neex Process Monitor...`));
445
- console.log(chalk_1.default.gray('Press Ctrl+C to exit'));
446
- const displayMonitor = async () => {
447
- // Clear screen
448
- process.stdout.write('\x1Bc');
449
- const processes = await pm.list();
450
- console.log(chalk_1.default.bold.cyan('Neex Process Monitor'));
451
- console.log(chalk_1.default.gray('─'.repeat(80)));
452
- if (processes.length === 0) {
453
- console.log(chalk_1.default.yellow(`${figures_1.default.info} No processes running`));
454
- }
455
- else {
456
- processes.forEach(proc => {
457
- const statusIcon = proc.status === 'online' ? chalk_1.default.green('●') :
458
- proc.status === 'stopped' ? chalk_1.default.gray('○') :
459
- proc.status === 'errored' ? chalk_1.default.red('●') : chalk_1.default.yellow('●');
460
- const uptime = formatUptime(proc.uptime);
461
- const pid = proc.pid ? `PID: ${proc.pid}` : 'PID: N/A';
462
- const memory = proc.status === 'online' ? formatMemory(proc.memory) : 'N/A';
463
- const cpu = proc.status === 'online' ? formatCpu(proc.cpu) : 'N/A';
464
- console.log(`${statusIcon} ${chalk_1.default.bold(proc.name)} (${proc.id}) - ${proc.status}`);
465
- console.log(` ${pid} | Uptime: ${uptime} | Restarts: ${proc.restarts} | CPU: ${cpu} | Memory: ${memory}`);
466
- console.log('');
467
- });
468
- }
469
- console.log(chalk_1.default.gray('─'.repeat(80)));
470
- console.log(`Last updated: ${new Date().toLocaleTimeString()}`);
471
- };
472
- // Initial display
473
- await displayMonitor();
474
- // Update every 2 seconds
475
- const monitorInterval = setInterval(displayMonitor, 2000);
476
- // Handle Ctrl+C
477
- process.on('SIGINT', () => {
478
- clearInterval(monitorInterval);
479
- console.log(chalk_1.default.yellow(`\n${figures_1.default.info} Monitor stopped`));
480
- process.exit(0);
481
- });
482
- }
483
- catch (error) {
484
- if (error instanceof Error) {
485
- console.error(chalk_1.default.red(`${figures_1.default.cross} Monitor Error: ${error.message}`));
486
- }
487
- else {
488
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown monitor error occurred`));
489
- }
490
- process.exit(1);
491
- }
492
- });
493
- // StartX command - اجرای بهینه برای پروداکشن
494
- program
495
- .command('startx <script>')
496
- .description('Start process optimized for production (auto-restart, clustering, monitoring)')
497
- .option('-n, --name <name>', 'Process name')
498
- .option('-i, --instances <number>', 'Number of instances (default: CPU cores)', parseInt)
499
- .option('--max-memory <size>', 'Max memory before restart (default: 1G)')
500
- .option('--cwd <path>', 'Working directory')
501
- .option('--env <env>', 'Environment variables (JSON string)')
502
- .action(async (script, options) => {
503
- try {
504
- const pm = await getOrCreateProcessManager();
505
- const os = require('os');
506
- // Resolve script path
507
- const scriptPath = path.resolve(script);
508
- if (!fs.existsSync(scriptPath)) {
509
- console.error(chalk_1.default.red(`${figures_1.default.cross} Script file not found: ${scriptPath}`));
510
- process.exit(1);
511
- }
512
- const instances = options.instances || os.cpus().length;
513
- const processName = options.name || path.basename(script, path.extname(script));
514
- console.log(chalk_1.default.blue(`${figures_1.default.info} Starting production-optimized process...`));
515
- console.log(chalk_1.default.blue(`${figures_1.default.info} Script: ${scriptPath}`));
516
- console.log(chalk_1.default.blue(`${figures_1.default.info} Instances: ${instances}`));
517
- console.log(chalk_1.default.blue(`${figures_1.default.info} Max Memory: ${options.maxMemory || '1G'}`));
518
- const baseConfig = {
519
- id: '',
520
- name: processName,
521
- script: scriptPath,
522
- cwd: options.cwd ? path.resolve(options.cwd) : process.cwd(),
523
- env: {
524
- NODE_ENV: 'production',
525
- ...(options.env ? JSON.parse(options.env) : {})
526
- },
527
- instances: 1,
528
- autorestart: true,
529
- max_restarts: 50,
530
- restart_delay: 1000,
531
- watch: false,
532
- max_memory_restart: options.maxMemory || '1G',
533
- time: true,
534
- merge_logs: false
535
- };
536
- const startedProcesses = [];
537
- // Start multiple instances
538
- for (let i = 0; i < instances; i++) {
539
- const config = {
540
- ...baseConfig,
541
- name: instances > 1 ? `${processName}-${i}` : processName
542
- };
543
- try {
544
- const id = await pm.start(config);
545
- startedProcesses.push(id);
546
- console.log(chalk_1.default.green(`${figures_1.default.tick} Instance ${i + 1}/${instances} started (ID: ${id})`));
547
- // Small delay between starts
548
- if (i < instances - 1) {
549
- await new Promise(resolve => setTimeout(resolve, 500));
550
- }
551
- }
552
- catch (error) {
553
- console.error(chalk_1.default.red(`${figures_1.default.cross} Failed to start instance ${i + 1}: ${error.message}`));
554
- }
555
- }
556
- if (startedProcesses.length > 0) {
557
- // Auto-save configuration
558
- await pm.save();
559
- console.log(chalk_1.default.green(`\n${figures_1.default.tick} Production deployment completed!`));
560
- console.log(chalk_1.default.blue(`${figures_1.default.info} Started ${startedProcesses.length}/${instances} instances`));
561
- console.log(chalk_1.default.blue(`${figures_1.default.info} Configuration saved automatically`));
562
- console.log(chalk_1.default.blue(`${figures_1.default.info} Use 'neex monitor' to watch processes`));
563
- console.log(chalk_1.default.blue(`${figures_1.default.info} Use 'neex logs <id>' to view logs`));
564
- }
565
- else {
566
- console.error(chalk_1.default.red(`${figures_1.default.cross} Failed to start any instances`));
567
- process.exit(1);
568
- }
569
- }
570
- catch (error) {
571
- if (error instanceof Error) {
572
- console.error(chalk_1.default.red(`${figures_1.default.cross} StartX Error: ${error.message}`));
573
- }
574
- else {
575
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown startx error occurred`));
576
- }
577
- process.exit(1);
578
- }
579
- });
580
- //stopx command - توقف بهینه برای پروداکشن
581
- program
582
- .command('stopx <name>')
583
- .description('Stop all instances of a production-optimized process by name')
584
- .action(async (name) => {
585
- try {
586
- const pm = await getOrCreateProcessManager();
587
- const processes = await pm.list(); // دریافت لیست تمام فرایندها
588
- // پیدا کردن تمام فرایندهایی که با نام اصلی (نه با ایندکس) شروع می‌شوند
589
- const processesToStop = processes.filter(p => p.name === name || p.name.startsWith(`${name}-`));
590
- if (processesToStop.length === 0) {
591
- console.log(chalk_1.default.yellow(`${figures_1.default.warning} No production process instances found for name "${name}".`));
592
- return;
593
- }
594
- console.log(chalk_1.default.blue(`${figures_1.default.info} Stopping ${processesToStop.length} instances of "${name}"...`));
595
- const stopPromises = processesToStop.map(async (p) => {
596
- try {
597
- await pm.stop(p.id);
598
- console.log(chalk_1.default.green(`${figures_1.default.tick} Stopped instance ${p.name} (ID: ${p.id})`));
599
- }
600
- catch (error) {
601
- if (error instanceof Error) {
602
- console.error(chalk_1.default.red(`${figures_1.default.cross} Failed to stop instance ${p.name} (ID: ${p.id}): ${error.message}`));
603
- }
604
- else {
605
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown error occurred while stopping instance ${p.name} (ID: ${p.id})`));
606
- }
607
- }
608
- });
609
- await Promise.all(stopPromises); // اجرای موازی توقف‌ها
610
- console.log(chalk_1.default.green(`\n${figures_1.default.tick} All specified production process instances have been processed.`));
611
- await pm.save(); // ذخیره تغییرات (حذف فرایندهای متوقف شده)
612
- }
613
- catch (error) {
614
- if (error instanceof Error) {
615
- console.error(chalk_1.default.red(`${figures_1.default.cross} StopX Error: ${error.message}`));
616
- }
617
- else {
618
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown stopx error occurred`));
619
- }
620
- process.exit(1);
621
- }
622
- });
623
- // Build command - Compile TypeScript project
624
- program
625
- .command('build <entry>')
626
- .description('Build TypeScript project from entry point')
627
- .option('-o, --out <dir>', 'Output directory', 'dist')
628
- .option('--tsconfig <path>', 'Path to tsconfig.json', 'tsconfig.json')
629
- .option('--watch', 'Watch for changes and rebuild')
630
- .action(async (entry, options) => {
631
- try {
632
- const entryPath = path.resolve(entry);
633
- const tsConfigPath = path.resolve(options.tsconfig);
634
- const outDir = path.resolve(options.out);
635
- // Check if entry file exists
636
- if (!fs.existsSync(entryPath)) {
637
- console.error(chalk_1.default.red(`${figures_1.default.cross} Entry point not found: ${entryPath}`));
638
- process.exit(1);
639
- }
640
- // Check if tsconfig exists
641
- if (!fs.existsSync(tsConfigPath)) {
642
- console.error(chalk_1.default.red(`${figures_1.default.cross} tsconfig.json not found at: ${tsConfigPath}`));
643
- process.exit(1);
644
- }
645
- // Create output directory if it doesn't exist
646
- if (!fs.existsSync(outDir)) {
647
- fs.mkdirSync(outDir, { recursive: true });
648
- }
649
- // Read tsconfig
650
- const tsConfig = JSON.parse(await fs_1.promises.readFile(tsConfigPath, 'utf8'));
651
- // Update tsconfig with entry point
652
- tsConfig.files = [entryPath];
653
- // Write temporary tsconfig
654
- const tempTsConfigPath = path.join(process.cwd(), '.neex.tsconfig.json');
655
- await fs_1.promises.writeFile(tempTsConfigPath, JSON.stringify(tsConfig, null, 2));
656
- console.log(chalk_1.default.blue(`${figures_1.default.info} Building TypeScript project...`));
657
- console.log(chalk_1.default.blue(`${figures_1.default.info} Entry Point: ${entryPath}`));
658
- console.log(chalk_1.default.blue(`${figures_1.default.info} Output: ${outDir}`));
659
- console.log(chalk_1.default.blue(`${figures_1.default.info} Using tsconfig: ${tempTsConfigPath}`));
660
- // Run tsc command
661
- const { spawn } = require('child_process');
662
- const tsc = spawn('tsc', [
663
- '--build',
664
- '--project', tempTsConfigPath,
665
- ...(options.watch ? ['--watch'] : [])
666
- ], {
667
- stdio: 'inherit',
668
- cwd: process.cwd()
669
- });
670
- tsc.on('close', (code) => {
671
- // Clean up temporary tsconfig
672
- fs.unlink(tempTsConfigPath, (err) => {
673
- if (err)
674
- console.error('Error cleaning up temporary tsconfig:', err);
675
- });
676
- if (code === 0) {
677
- console.log(chalk_1.default.green(`${figures_1.default.tick} Build completed successfully!`));
678
- console.log(chalk_1.default.blue(`${figures_1.default.info} Output files in: ${outDir}`));
679
- }
680
- else {
681
- console.error(chalk_1.default.red(`${figures_1.default.cross} Build failed with code ${code}`));
682
- process.exit(1);
683
- }
684
- });
685
- }
686
- catch (error) {
687
- if (error instanceof Error) {
688
- console.error(chalk_1.default.red(`${figures_1.default.cross} Build Error: ${error.message}`));
689
- }
690
- else {
691
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown build error occurred`));
692
- }
693
- process.exit(1);
694
- }
695
- });
696
- // Startup command - راه‌اندازی خودکار هنگام بوت
697
- program
698
- .command('startup')
699
- .description('Generate startup script for system boot')
700
- .option('--user <user>', 'User to run processes as')
701
- .action(async (options) => {
702
- try {
703
- const user = options.user || require('os').userInfo().username;
704
- const homeDir = require('os').homedir();
705
- const neexPath = process.argv[1]; // Path to neex executable
706
- const systemdService = `[Unit]
707
- Description=Neex Process Manager
708
- After=network.target
709
-
710
- [Service]
711
- Type=forking
712
- User=${user}
713
- WorkingDirectory=${homeDir}
714
- ExecStart=${neexPath} resurrect
715
- ExecReload=${neexPath} restart all
716
- ExecStop=${neexPath} stop all
717
- Restart=on-failure
718
- RestartSec=5
719
-
720
- [Install]
721
- WantedBy=multi-user.target`;
722
- const servicePath = '/etc/systemd/system/neex.service';
723
- console.log(chalk_1.default.blue(`${figures_1.default.info} Generating startup configuration...`));
724
- console.log(chalk_1.default.yellow(`${figures_1.default.warning} This requires sudo privileges`));
725
- console.log('\nSystemd service file content:');
726
- console.log(chalk_1.default.gray('─'.repeat(40)));
727
- console.log(systemdService);
728
- console.log(chalk_1.default.gray('─'.repeat(40)));
729
- console.log(`\n${chalk_1.default.bold('To enable startup on boot, run:')}`);
730
- console.log(chalk_1.default.cyan(`sudo tee ${servicePath} << 'EOF'`));
731
- console.log(systemdService);
732
- console.log(chalk_1.default.cyan('EOF'));
733
- console.log(chalk_1.default.cyan('sudo systemctl daemon-reload'));
734
- console.log(chalk_1.default.cyan('sudo systemctl enable neex'));
735
- console.log(chalk_1.default.cyan('sudo systemctl start neex'));
736
- console.log(`\n${chalk_1.default.bold('To check status:')}`);
737
- console.log(chalk_1.default.cyan('sudo systemctl status neex'));
738
- }
739
- catch (error) {
740
- if (error instanceof Error) {
741
- console.error(chalk_1.default.red(`${figures_1.default.cross} Startup Error: ${error.message}`));
742
- }
743
- else {
744
- console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown startup error occurred`));
745
- }
746
- process.exit(1);
747
- }
748
- });
749
- // Return cleanup function for process manager
750
- return {
751
- getProcessManager: () => processManager,
752
- cleanupProcess: async () => {
753
- if (processManager) {
754
- await processManager.dispose();
755
- }
756
- }
757
- };
758
- }
759
- exports.addProcessCommands = addProcessCommands;