neex 0.6.47 → 0.6.50

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.
@@ -6,55 +6,250 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.addStartCommands = void 0;
7
7
  const start_manager_js_1 = require("../start-manager.js");
8
8
  const logger_manager_js_1 = require("../logger-manager.js");
9
- const path_1 = __importDefault(require("path"));
10
- const fs_1 = __importDefault(require("fs"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const figures_1 = __importDefault(require("figures"));
11
+ const os_1 = __importDefault(require("os"));
11
12
  function addStartCommands(program) {
12
- let manager = null;
13
- const startCommand = program
13
+ let startManager = null;
14
+ // Main start command
15
+ program
14
16
  .command('start [entry]')
15
- .description('Start a production-ready application')
16
- .option('-n, --name <name>', 'Application name')
17
- .option('-w, --watch', 'Watch for file changes and restart the application', false)
18
- .option('--quiet', 'Suppress all output', false)
19
- .option('--color', 'Force color output', true)
20
- .option('--verbose', 'Enable verbose logging', false)
21
- .option('--node-args <args>', 'Arguments to pass to the node process', (value) => value.split(' '), [])
17
+ .description('Start the production server (default: dist/index.js)')
18
+ .option('-p, --port <port>', 'Port to run the server on', '3000')
19
+ .option('-h, --host <host>', 'Host to bind the server to', '0.0.0.0')
20
+ .option('-e, --env <env>', 'Environment mode', 'production')
21
+ .option('-w, --watch', 'Watch for file changes and restart')
22
+ .option('-c, --cluster', 'Enable cluster mode')
23
+ .option('--workers <count>', 'Number of worker processes (default: CPU count)', os_1.default.cpus().length.toString())
24
+ .option('-m, --memory <mb>', 'Memory limit in MB', '512')
25
+ .option('-t, --timeout <ms>', 'Startup timeout in milliseconds', '30000')
26
+ .option('--graceful-timeout <ms>', 'Graceful shutdown timeout in milliseconds', '5000')
27
+ .option('-v, --verbose', 'Verbose output')
28
+ .option('-q, --quiet', 'Quiet output')
29
+ .option('--no-color', 'Disable colored output')
30
+ .option('--log-level <level>', 'Log level (error, warn, info, debug)', 'info')
31
+ .option('--node-args <args>', 'Additional Node.js arguments (comma-separated)')
32
+ .option('--inspect', 'Enable Node.js inspector')
33
+ .option('--inspect-port <port>', 'Inspector port', '9229')
34
+ .option('--pid <file>', 'Write process ID to file')
35
+ .option('--restart', 'Auto-restart on failure', true)
36
+ .option('--restart-delay <ms>', 'Delay between restarts in milliseconds', '1000')
37
+ .option('--max-restarts <count>', 'Maximum restart attempts', '10')
22
38
  .action(async (entry, options) => {
23
- let entryPoint = entry;
24
- if (!entryPoint) {
25
- const defaultPath = path_1.default.join(process.cwd(), 'dist', 'index.js');
26
- if (fs_1.default.existsSync(defaultPath)) {
27
- entryPoint = defaultPath;
39
+ try {
40
+ const entryFile = entry || 'dist/index.js';
41
+ if (!options.quiet) {
42
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue(figures_1.default.info)} Starting production server...`, 'info');
43
+ }
44
+ const nodeArgs = options.nodeArgs ?
45
+ options.nodeArgs.split(',').map((arg) => arg.trim()) : [];
46
+ startManager = new start_manager_js_1.StartManager({
47
+ entry: entryFile,
48
+ port: parseInt(options.port),
49
+ host: options.host,
50
+ env: options.env,
51
+ watch: options.watch,
52
+ cluster: options.cluster,
53
+ workers: parseInt(options.workers),
54
+ memory: parseInt(options.memory),
55
+ timeout: parseInt(options.timeout),
56
+ gracefulTimeout: parseInt(options.gracefulTimeout),
57
+ verbose: options.verbose,
58
+ quiet: options.quiet,
59
+ color: options.color,
60
+ logLevel: options.logLevel,
61
+ nodeArgs,
62
+ inspect: options.inspect,
63
+ inspectPort: parseInt(options.inspectPort),
64
+ pid: options.pid,
65
+ restart: options.restart,
66
+ restartDelay: parseInt(options.restartDelay),
67
+ maxRestarts: parseInt(options.maxRestarts)
68
+ });
69
+ await startManager.start();
70
+ }
71
+ catch (error) {
72
+ if (error instanceof Error) {
73
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Start failed: ${error.message}`, 'error');
28
74
  }
29
75
  else {
30
- logger_manager_js_1.loggerManager.printLine('Entry file not found. Please specify an entry file or build the project first.', 'error');
31
- process.exit(1);
76
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} An unknown start error occurred`, 'error');
77
+ }
78
+ process.exit(1);
79
+ }
80
+ });
81
+ // Quick start command for development
82
+ program
83
+ .command('serve [entry]')
84
+ .description('Quick start with watch mode (development)')
85
+ .option('-p, --port <port>', 'Port to run the server on', '3000')
86
+ .option('-v, --verbose', 'Verbose output')
87
+ .action(async (entry, options) => {
88
+ try {
89
+ const entryFile = entry || 'dist/index.js';
90
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue(figures_1.default.info)} Starting development server...`, 'info');
91
+ startManager = new start_manager_js_1.StartManager({
92
+ entry: entryFile,
93
+ port: parseInt(options.port),
94
+ host: '127.0.0.1',
95
+ env: 'development',
96
+ watch: true,
97
+ cluster: false,
98
+ workers: 1,
99
+ memory: 256,
100
+ timeout: 15000,
101
+ gracefulTimeout: 3000,
102
+ verbose: options.verbose,
103
+ quiet: false,
104
+ color: true,
105
+ logLevel: 'info',
106
+ nodeArgs: [],
107
+ inspect: false,
108
+ inspectPort: 9229,
109
+ pid: '',
110
+ restart: true,
111
+ restartDelay: 500,
112
+ maxRestarts: 50
113
+ });
114
+ await startManager.start();
115
+ }
116
+ catch (error) {
117
+ if (error instanceof Error) {
118
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Serve failed: ${error.message}`, 'error');
32
119
  }
120
+ else {
121
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} An unknown serve error occurred`, 'error');
122
+ }
123
+ process.exit(1);
33
124
  }
34
- const startOptions = {
35
- entry: entryPoint,
36
- name: options.name,
37
- watch: options.watch,
38
- quiet: options.quiet,
39
- color: options.color,
40
- verbose: options.verbose,
41
- nodeArgs: options.nodeArgs,
42
- };
43
- manager = new start_manager_js_1.StartManager(startOptions);
125
+ });
126
+ // Production deployment command
127
+ program
128
+ .command('deploy [entry]')
129
+ .description('Deploy to production with optimal settings')
130
+ .option('-p, --port <port>', 'Port to run the server on', process.env.PORT || '3000')
131
+ .option('-w, --workers <count>', 'Number of worker processes', os_1.default.cpus().length.toString())
132
+ .option('-m, --memory <mb>', 'Memory limit in MB', '1024')
133
+ .option('--pid <file>', 'Write process ID to file', 'server.pid')
134
+ .option('-v, --verbose', 'Verbose output')
135
+ .action(async (entry, options) => {
44
136
  try {
45
- await manager.start();
137
+ const entryFile = entry || 'dist/index.js';
138
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue(figures_1.default.info)} Deploying to production...`, 'info');
139
+ startManager = new start_manager_js_1.StartManager({
140
+ entry: entryFile,
141
+ port: parseInt(options.port),
142
+ host: '0.0.0.0',
143
+ env: 'production',
144
+ watch: false,
145
+ cluster: true,
146
+ workers: parseInt(options.workers),
147
+ memory: parseInt(options.memory),
148
+ timeout: 30000,
149
+ gracefulTimeout: 10000,
150
+ verbose: options.verbose,
151
+ quiet: false,
152
+ color: false,
153
+ logLevel: 'warn',
154
+ nodeArgs: ['--optimize-for-size'],
155
+ inspect: false,
156
+ inspectPort: 9229,
157
+ pid: options.pid,
158
+ restart: true,
159
+ restartDelay: 2000,
160
+ maxRestarts: 5
161
+ });
162
+ await startManager.start();
46
163
  }
47
164
  catch (error) {
48
- logger_manager_js_1.loggerManager.printLine(error.message, 'error');
165
+ if (error instanceof Error) {
166
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Deploy failed: ${error.message}`, 'error');
167
+ }
168
+ else {
169
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} An unknown deploy error occurred`, 'error');
170
+ }
49
171
  process.exit(1);
50
172
  }
51
173
  });
52
- return {
53
- cleanupStart: async () => {
54
- if (manager) {
55
- await manager.stop();
174
+ // Health check command
175
+ program
176
+ .command('health [url]')
177
+ .description('Check server health')
178
+ .option('-t, --timeout <ms>', 'Request timeout in milliseconds', '5000')
179
+ .option('-i, --interval <ms>', 'Check interval in milliseconds', '1000')
180
+ .option('-c, --count <number>', 'Number of checks', '1')
181
+ .action(async (url, options) => {
182
+ const checkUrl = url || 'http://localhost:3000/health';
183
+ const timeout = parseInt(options.timeout);
184
+ const interval = parseInt(options.interval);
185
+ const count = parseInt(options.count);
186
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue(figures_1.default.info)} Health check: ${checkUrl}`, 'info');
187
+ for (let i = 0; i < count; i++) {
188
+ try {
189
+ const controller = new AbortController();
190
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
191
+ const response = await fetch(checkUrl, {
192
+ signal: controller.signal
193
+ });
194
+ clearTimeout(timeoutId);
195
+ if (response.ok) {
196
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.tick)} Health check ${i + 1}/${count}: OK (${response.status})`, 'info');
197
+ }
198
+ else {
199
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Health check ${i + 1}/${count}: Failed (${response.status})`, 'error');
200
+ }
201
+ }
202
+ catch (error) {
203
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Health check ${i + 1}/${count}: Error (${error.message})`, 'error');
204
+ }
205
+ if (i < count - 1) {
206
+ await new Promise(resolve => setTimeout(resolve, interval));
207
+ }
208
+ }
209
+ });
210
+ // Cleanup function
211
+ const cleanupStart = async () => {
212
+ if (startManager) {
213
+ try {
214
+ await startManager.stop();
215
+ startManager = null;
216
+ }
217
+ catch (error) {
218
+ // Ignore cleanup errors
56
219
  }
57
- },
220
+ }
221
+ };
222
+ // Handle process termination
223
+ const handleExit = (signal) => {
224
+ if (startManager) {
225
+ logger_manager_js_1.loggerManager.printLine(`\n${chalk_1.default.yellow(figures_1.default.warning)} Received ${signal}, shutting down gracefully...`, 'info');
226
+ cleanupStart().then(() => {
227
+ process.exit(0);
228
+ }).catch(() => {
229
+ process.exit(1);
230
+ });
231
+ }
232
+ else {
233
+ process.exit(0);
234
+ }
58
235
  };
236
+ // Register signal handlers
237
+ process.on('SIGINT', () => handleExit('SIGINT'));
238
+ process.on('SIGTERM', () => handleExit('SIGTERM'));
239
+ process.on('SIGQUIT', () => handleExit('SIGQUIT'));
240
+ // Handle uncaught exceptions
241
+ process.on('uncaughtException', (error) => {
242
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Uncaught exception: ${error.message}`, 'error');
243
+ cleanupStart().then(() => {
244
+ process.exit(1);
245
+ });
246
+ });
247
+ process.on('unhandledRejection', (reason, promise) => {
248
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Unhandled rejection at: ${promise} reason: ${reason}`, 'error');
249
+ cleanupStart().then(() => {
250
+ process.exit(1);
251
+ });
252
+ });
253
+ return { cleanupStart };
59
254
  }
60
255
  exports.addStartCommands = addStartCommands;
@@ -46,97 +46,20 @@ class DevManager {
46
46
  }
47
47
  }
48
48
  }
49
- detectRuntime() {
50
- // Check if we're running in Bun
51
- if (typeof globalThis.Bun !== 'undefined' || process.versions.bun) {
52
- return 'bun';
53
- }
54
- // Check if we're running in Deno
55
- if (typeof globalThis.Deno !== 'undefined') {
56
- return 'deno';
57
- }
58
- return 'node';
59
- }
60
49
  getExecuteCommand() {
61
50
  if (this.options.execCommand) {
62
51
  const parts = this.options.execCommand.split(' ');
63
52
  return { command: parts[0], args: [...parts.slice(1), this.options.file] };
64
53
  }
65
- const runtime = this.detectRuntime();
66
- const isTypeScript = this.options.file.endsWith('.ts') || this.options.useTypeScript;
67
- let command;
68
- let args = [];
69
- switch (runtime) {
70
- case 'bun':
71
- command = 'bun';
72
- args = ['run', this.options.file];
73
- break;
74
- case 'deno':
75
- command = 'deno';
76
- args = ['run', '--allow-all', this.options.file];
77
- break;
78
- case 'node':
79
- default:
80
- command = 'node';
81
- if (isTypeScript) {
82
- // Try different TypeScript execution methods
83
- if (this.commandExists('tsx')) {
84
- command = 'tsx';
85
- args = [this.options.file];
86
- }
87
- else if (this.commandExists('ts-node')) {
88
- command = 'ts-node';
89
- args = [this.options.file];
90
- }
91
- else {
92
- // Fallback: try to use node with --loader
93
- const tsNodePath = this.findTsNodePath();
94
- if (tsNodePath) {
95
- args = ['--loader', tsNodePath, this.options.file];
96
- }
97
- else {
98
- throw new Error('TypeScript execution not available. Please install tsx or ts-node');
99
- }
100
- }
101
- }
102
- else {
103
- // Regular JavaScript file
104
- args = [this.options.file];
105
- }
106
- break;
107
- }
108
- // Add inspect flags for Node.js
109
- if (runtime === 'node' && command === 'node') {
110
- if (this.options.inspect) {
111
- args.unshift('--inspect');
112
- }
113
- if (this.options.inspectBrk) {
114
- args.unshift('--inspect-brk');
115
- }
116
- }
117
- return { command, args };
118
- }
119
- commandExists(command) {
120
- try {
121
- const { execSync } = require('child_process');
122
- execSync(`which ${command}`, { stdio: 'ignore' });
123
- return true;
124
- }
125
- catch (_a) {
126
- return false;
54
+ // Default to tsx for TypeScript files
55
+ const args = [this.options.file];
56
+ if (this.options.inspect) {
57
+ args.unshift('--inspect');
127
58
  }
128
- }
129
- findTsNodePath() {
130
- const paths = [
131
- path_1.default.join(process.cwd(), 'node_modules', 'ts-node', 'esm.mjs'),
132
- path_1.default.join(process.cwd(), 'node_modules', 'ts-node', 'register.js'),
133
- ];
134
- for (const tsPath of paths) {
135
- if (fs_1.default.existsSync(tsPath)) {
136
- return tsPath;
137
- }
59
+ if (this.options.inspectBrk) {
60
+ args.unshift('--inspect-brk');
138
61
  }
139
- return null;
62
+ return { command: 'tsx', args };
140
63
  }
141
64
  clearConsole() {
142
65
  if (this.options.clearConsole && process.stdout.isTTY) {
@@ -149,66 +72,50 @@ class DevManager {
149
72
  return;
150
73
  }
151
74
  this.loadEnvFile();
152
- try {
153
- const { command, args } = this.getExecuteCommand();
154
- if (this.options.verbose) {
155
- logger_manager_js_1.loggerManager.printLine(`Executing: ${command} ${args.join(' ')}`, 'info');
75
+ const { command, args } = this.getExecuteCommand();
76
+ if (this.options.verbose) {
77
+ logger_manager_js_1.loggerManager.printLine(`Executing: ${command} ${args.join(' ')}`, 'info');
78
+ }
79
+ this.process = (0, child_process_1.spawn)(command, args, {
80
+ stdio: ['ignore', 'pipe', 'pipe'],
81
+ shell: false,
82
+ env: {
83
+ ...process.env,
84
+ NODE_ENV: process.env.NODE_ENV || 'development',
85
+ FORCE_COLOR: this.options.color ? '1' : '0'
86
+ },
87
+ detached: true
88
+ });
89
+ this.startTime = new Date();
90
+ this.restartCount++;
91
+ if (!this.options.quiet) {
92
+ const timestamp = new Date().toLocaleTimeString();
93
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.play)} Started ${chalk_1.default.cyan(this.options.file)} ${chalk_1.default.dim(`(${timestamp})`)}`, 'info');
94
+ }
95
+ (_a = this.process.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
96
+ if (!this.options.quiet) {
97
+ process.stdout.write(data);
156
98
  }
157
- this.process = (0, child_process_1.spawn)(command, args, {
158
- stdio: ['ignore', 'pipe', 'pipe'],
159
- shell: false,
160
- env: {
161
- ...process.env,
162
- NODE_ENV: process.env.NODE_ENV || 'development',
163
- FORCE_COLOR: this.options.color ? '1' : '0',
164
- // Add common TypeScript environment variables
165
- TS_NODE_COMPILER_OPTIONS: '{"module":"commonjs","target":"es2020"}',
166
- TS_NODE_TRANSPILE_ONLY: 'true'
167
- },
168
- detached: true
169
- });
170
- this.startTime = new Date();
171
- this.restartCount++;
99
+ });
100
+ (_b = this.process.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
172
101
  if (!this.options.quiet) {
173
- const timestamp = new Date().toLocaleTimeString();
174
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.play)} Started ${chalk_1.default.cyan(this.options.file)} ${chalk_1.default.dim(`(${timestamp})`)}`, 'info');
102
+ process.stderr.write(data);
175
103
  }
176
- (_a = this.process.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
177
- if (!this.options.quiet) {
178
- process.stdout.write(data);
179
- }
180
- });
181
- (_b = this.process.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
182
- if (!this.options.quiet) {
183
- process.stderr.write(data);
184
- }
185
- });
186
- this.process.on('error', (error) => {
187
- logger_manager_js_1.loggerManager.printLine(`Process error: ${error.message}`, 'error');
188
- // Provide helpful error messages
189
- if (error.message.includes('ENOENT')) {
190
- logger_manager_js_1.loggerManager.printLine(`Command not found. Make sure the required runtime is installed.`, 'error');
191
- }
192
- else if (error.message.includes('EACCES')) {
193
- logger_manager_js_1.loggerManager.printLine(`Permission denied. The command might not be executable.`, 'error');
194
- }
195
- });
196
- this.process.on('exit', (code, signal) => {
197
- if (this.process) {
198
- this.process = null;
199
- if (!this.isRestarting) {
200
- if (code !== 0) {
201
- const duration = this.startTime ? Date.now() - this.startTime.getTime() : 0;
202
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Process exited with code ${code} after ${duration}ms`, 'error');
203
- }
104
+ });
105
+ this.process.on('error', (error) => {
106
+ logger_manager_js_1.loggerManager.printLine(`Process error: ${error.message}`, 'error');
107
+ });
108
+ this.process.on('exit', (code, signal) => {
109
+ if (this.process) {
110
+ this.process = null;
111
+ if (!this.isRestarting) {
112
+ if (code !== 0) {
113
+ const duration = this.startTime ? Date.now() - this.startTime.getTime() : 0;
114
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Process exited with code ${code} after ${duration}ms`, 'error');
204
115
  }
205
116
  }
206
- });
207
- }
208
- catch (error) {
209
- logger_manager_js_1.loggerManager.printLine(`Failed to start process: ${error.message}`, 'error');
210
- throw error;
211
- }
117
+ }
118
+ });
212
119
  }
213
120
  async stopProcess() {
214
121
  if (!this.process) {
@@ -275,12 +182,6 @@ class DevManager {
275
182
  '**/dist/**',
276
183
  '**/build/**',
277
184
  '**/*.log',
278
- '**/.next/**',
279
- '**/.nuxt/**',
280
- '**/.vscode/**',
281
- '**/.idea/**',
282
- '**/coverage/**',
283
- '**/*.map',
284
185
  ...this.options.ignore.map(pattern => `**/${pattern}/**`)
285
186
  ];
286
187
  this.watcher = (0, chokidar_1.watch)(watchPatterns, {
@@ -288,11 +189,7 @@ class DevManager {
288
189
  ignoreInitial: true,
289
190
  followSymlinks: false,
290
191
  usePolling: false,
291
- atomic: 300,
292
- awaitWriteFinish: {
293
- stabilityThreshold: 100,
294
- pollInterval: 50
295
- }
192
+ atomic: 300
296
193
  });
297
194
  this.watcher.on('change', (filePath) => {
298
195
  if (this.options.verbose) {
@@ -331,7 +228,6 @@ class DevManager {
331
228
  logger_manager_js_1.loggerManager.printLine(`Target file: ${this.options.file}`, 'info');
332
229
  logger_manager_js_1.loggerManager.printLine(`Watch patterns: ${this.options.watch.join(', ')}`, 'info');
333
230
  logger_manager_js_1.loggerManager.printLine(`Restart delay: ${this.options.delay}ms`, 'info');
334
- logger_manager_js_1.loggerManager.printLine(`Runtime: ${this.detectRuntime()}`, 'info');
335
231
  }
336
232
  this.setupWatcher();
337
233
  await this.startProcess();