neex 0.6.90 → 0.6.92
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/dist/src/build-manager.js +2 -2
- package/dist/src/commands/build-commands.js +16 -34
- package/dist/src/commands/dev-commands.js +109 -66
- package/dist/src/commands/start-commands.js +16 -43
- package/dist/src/dev-manager.js +199 -216
- package/dist/src/start-manager.js +2 -2
- package/package.json +1 -1
|
@@ -352,7 +352,7 @@ class BuildManager {
|
|
|
352
352
|
}
|
|
353
353
|
async stop() {
|
|
354
354
|
if (!this.options.quiet) {
|
|
355
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow(
|
|
355
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow('⏹')} Stopping build process...`, 'info');
|
|
356
356
|
}
|
|
357
357
|
if (this.watcher) {
|
|
358
358
|
await this.watcher.close();
|
|
@@ -360,7 +360,7 @@ class BuildManager {
|
|
|
360
360
|
}
|
|
361
361
|
await this.stopProcess();
|
|
362
362
|
if (this.buildCount > 0 && !this.options.quiet) {
|
|
363
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue(
|
|
363
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue('ℹ')} Build process stopped after ${this.buildCount} build(s).`, 'info');
|
|
364
364
|
}
|
|
365
365
|
}
|
|
366
366
|
}
|
|
@@ -48,6 +48,20 @@ function addBuildCommands(program) {
|
|
|
48
48
|
color: options.color,
|
|
49
49
|
analyze: options.analyze
|
|
50
50
|
});
|
|
51
|
+
// --- Signal Handlers for Build ---
|
|
52
|
+
const cleanupAndExit = (signal) => {
|
|
53
|
+
if (buildManager) {
|
|
54
|
+
logger_manager_js_1.loggerManager.printLine(`\n${chalk_1.default.yellow('⏹')} Received ${signal}, shutting down...`, 'info');
|
|
55
|
+
buildManager.stop().then(() => process.exit(0));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const sigintHandler = () => cleanupAndExit('SIGINT');
|
|
62
|
+
const sigtermHandler = () => cleanupAndExit('SIGTERM');
|
|
63
|
+
process.on('SIGINT', sigintHandler);
|
|
64
|
+
process.on('SIGTERM', sigtermHandler);
|
|
51
65
|
await buildManager.build();
|
|
52
66
|
// If not in watch mode, show completion message
|
|
53
67
|
if (!options.watch && !options.quiet) {
|
|
@@ -103,40 +117,8 @@ function addBuildCommands(program) {
|
|
|
103
117
|
process.exit(1);
|
|
104
118
|
}
|
|
105
119
|
});
|
|
106
|
-
// Cleanup function
|
|
107
|
-
const cleanupBuild = async () => {
|
|
108
|
-
if (buildManager) {
|
|
109
|
-
try {
|
|
110
|
-
await buildManager.stop();
|
|
111
|
-
buildManager = null;
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
// Ignore cleanup errors
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
// Handle process termination
|
|
119
|
-
const handleExit = (signal) => {
|
|
120
|
-
if (buildManager) {
|
|
121
|
-
logger_manager_js_1.loggerManager.printLine(`\n${chalk_1.default.yellow(figures_1.default.warning)} Received ${signal}, stopping build process...`, 'info');
|
|
122
|
-
cleanupBuild().then(() => {
|
|
123
|
-
process.exit(0);
|
|
124
|
-
}).catch(() => {
|
|
125
|
-
process.exit(1);
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
process.exit(0);
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
// Register signal handlers
|
|
133
|
-
process.on('SIGINT', () => handleExit('SIGINT'));
|
|
134
|
-
process.on('SIGTERM', () => handleExit('SIGTERM'));
|
|
135
|
-
process.on('exit', () => {
|
|
136
|
-
if (buildManager) {
|
|
137
|
-
cleanupBuild();
|
|
138
|
-
}
|
|
139
|
-
});
|
|
120
|
+
// Cleanup function is no longer needed here as it's handled within the command
|
|
121
|
+
const cleanupBuild = async () => { };
|
|
140
122
|
return { cleanupBuild };
|
|
141
123
|
}
|
|
142
124
|
exports.addBuildCommands = addBuildCommands;
|
|
@@ -7,45 +7,36 @@ exports.addDevCommands = void 0;
|
|
|
7
7
|
const dev_manager_js_1 = require("../dev-manager.js");
|
|
8
8
|
const logger_manager_js_1 = require("../logger-manager.js");
|
|
9
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
-
const figures_1 = __importDefault(require("figures"));
|
|
11
10
|
function addDevCommands(program) {
|
|
12
11
|
let devManager = null;
|
|
13
|
-
//
|
|
12
|
+
// Ultra-fast dev command optimized for speed
|
|
14
13
|
program
|
|
15
14
|
.command('dev [file]')
|
|
16
|
-
.description('Start TypeScript development server
|
|
17
|
-
.option('-w, --watch <patterns>', 'Watch
|
|
18
|
-
.option('-i, --ignore <patterns>', 'Ignore patterns (comma-separated)', 'node_modules,dist,build,.git
|
|
19
|
-
.option('-e, --ext <extensions>', 'File extensions to watch
|
|
20
|
-
.option('-d, --delay <ms>', '
|
|
21
|
-
.option('--fast', '
|
|
22
|
-
.option('-c, --no-color', 'Disable colored output')
|
|
23
|
-
.option('-q, --quiet', 'Reduce output verbosity')
|
|
24
|
-
.option('-v, --verbose', 'Verbose output')
|
|
15
|
+
.description('Start ultra-fast TypeScript development server (like tsx)')
|
|
16
|
+
.option('-w, --watch <patterns>', 'Watch patterns (comma-separated)', 'src/**/*')
|
|
17
|
+
.option('-i, --ignore <patterns>', 'Ignore patterns (comma-separated)', 'node_modules,dist,build,.git')
|
|
18
|
+
.option('-e, --ext <extensions>', 'File extensions to watch', 'ts,tsx,js,jsx')
|
|
19
|
+
.option('-d, --delay <ms>', 'Restart delay in milliseconds', parseInt, 100)
|
|
20
|
+
.option('--fast', 'Ultra-fast mode (50ms delay)')
|
|
25
21
|
.option('--no-clear', 'Don\'t clear console on restart')
|
|
22
|
+
.option('--no-color', 'Disable colored output')
|
|
23
|
+
.option('-q, --quiet', 'Minimal output')
|
|
24
|
+
.option('-v, --verbose', 'Verbose logging')
|
|
26
25
|
.option('--inspect', 'Enable Node.js inspector')
|
|
27
|
-
.option('--inspect-brk', 'Enable Node.js inspector with
|
|
28
|
-
.option('--env <file>', '
|
|
29
|
-
.option('--exec <command>', '
|
|
30
|
-
.option('--tsconfig <path>', '
|
|
31
|
-
.option('--no-source-maps', 'Disable source
|
|
32
|
-
.option('--transpile-only', 'Skip type checking
|
|
33
|
-
.option('--node-args <args>', '
|
|
26
|
+
.option('--inspect-brk', 'Enable Node.js inspector with breakpoint')
|
|
27
|
+
.option('--env <file>', 'Environment file to load', '.env')
|
|
28
|
+
.option('--exec <command>', 'Custom command to execute')
|
|
29
|
+
.option('--tsconfig <path>', 'TypeScript config file path')
|
|
30
|
+
.option('--no-source-maps', 'Disable source map generation')
|
|
31
|
+
.option('--transpile-only', 'Skip type checking (faster)')
|
|
32
|
+
.option('--node-args <args>', 'Node.js arguments (comma-separated)', '')
|
|
34
33
|
.action(async (file, options) => {
|
|
35
34
|
try {
|
|
36
35
|
const targetFile = file || 'src/index.ts';
|
|
37
|
-
|
|
38
|
-
const delay = options.fast ? 200 : options.delay;
|
|
36
|
+
const delay = options.fast ? 50 : options.delay;
|
|
39
37
|
if (!options.quiet) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim('Features:')}`, 'info');
|
|
43
|
-
logger_manager_js_1.loggerManager.printLine(` ${chalk_1.default.green('✓')} Built-in TypeScript compilation`, 'info');
|
|
44
|
-
logger_manager_js_1.loggerManager.printLine(` ${chalk_1.default.green('✓')} Hot reloading with intelligent caching`, 'info');
|
|
45
|
-
logger_manager_js_1.loggerManager.printLine(` ${chalk_1.default.green('✓')} Source map support`, 'info');
|
|
46
|
-
logger_manager_js_1.loggerManager.printLine(` ${chalk_1.default.green('✓')} Fast transpilation mode`, 'info');
|
|
47
|
-
logger_manager_js_1.loggerManager.printLine(` ${chalk_1.default.green('✓')} Dependency tracking`, 'info');
|
|
48
|
-
}
|
|
38
|
+
console.log(''); // Empty line for better visual separation
|
|
39
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue('ℹ')} Starting ${chalk_1.default.cyan('neex dev')} for ${chalk_1.default.cyan(targetFile)}`, 'info');
|
|
49
40
|
}
|
|
50
41
|
devManager = new dev_manager_js_1.DevManager({
|
|
51
42
|
file: targetFile,
|
|
@@ -66,84 +57,136 @@ function addDevCommands(program) {
|
|
|
66
57
|
transpileOnly: options.transpileOnly,
|
|
67
58
|
nodeArgs: options.nodeArgs ? options.nodeArgs.split(',').map((arg) => arg.trim()) : []
|
|
68
59
|
});
|
|
60
|
+
// --- Signal Handlers for Dev ---
|
|
61
|
+
const cleanupAndExit = () => {
|
|
62
|
+
if (devManager) {
|
|
63
|
+
logger_manager_js_1.loggerManager.printLine(`\n${chalk_1.default.yellow('⏹')} Received SIGINT, shutting down...`, 'info');
|
|
64
|
+
devManager.stop().then(() => process.exit(0));
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const sigintHandler = () => cleanupAndExit();
|
|
68
|
+
const sigtermHandler = () => cleanupAndExit();
|
|
69
|
+
process.on('SIGINT', sigintHandler);
|
|
70
|
+
process.on('SIGTERM', sigtermHandler);
|
|
69
71
|
await devManager.start();
|
|
70
72
|
}
|
|
71
73
|
catch (error) {
|
|
72
74
|
if (error instanceof Error) {
|
|
73
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(
|
|
75
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red('✖')} ${error.message}`, 'error');
|
|
74
76
|
}
|
|
75
77
|
else {
|
|
76
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(
|
|
78
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red('✖')} Unknown error occurred`, 'error');
|
|
77
79
|
}
|
|
78
80
|
process.exit(1);
|
|
79
81
|
}
|
|
80
82
|
});
|
|
81
|
-
//
|
|
83
|
+
// Clean cache command
|
|
82
84
|
program
|
|
83
85
|
.command('dev:clean')
|
|
84
|
-
.description('Clean development
|
|
86
|
+
.description('Clean development cache and temp files')
|
|
85
87
|
.action(() => {
|
|
86
88
|
const path = require('path');
|
|
87
89
|
const fs = require('fs');
|
|
88
90
|
const tempDir = path.join(process.cwd(), '.neex-temp');
|
|
91
|
+
const nodeModulesCache = path.join(process.cwd(), 'node_modules/.cache');
|
|
92
|
+
let cleaned = false;
|
|
89
93
|
if (fs.existsSync(tempDir)) {
|
|
90
94
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
91
|
-
|
|
95
|
+
cleaned = true;
|
|
96
|
+
}
|
|
97
|
+
if (fs.existsSync(nodeModulesCache)) {
|
|
98
|
+
try {
|
|
99
|
+
fs.rmSync(nodeModulesCache, { recursive: true, force: true });
|
|
100
|
+
cleaned = true;
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
// Ignore cache cleanup errors
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (cleaned) {
|
|
107
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green('✓')} Cache cleaned successfully`, 'info');
|
|
92
108
|
}
|
|
93
109
|
else {
|
|
94
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.
|
|
110
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue('ℹ')} No cache to clean`, 'info');
|
|
95
111
|
}
|
|
96
112
|
});
|
|
113
|
+
// TypeScript config check
|
|
97
114
|
program
|
|
98
115
|
.command('dev:check')
|
|
99
|
-
.description('Check TypeScript configuration
|
|
100
|
-
.option('--tsconfig <path>', '
|
|
116
|
+
.description('Check TypeScript configuration')
|
|
117
|
+
.option('--tsconfig <path>', 'TypeScript config file path')
|
|
101
118
|
.action((options) => {
|
|
102
119
|
const path = require('path');
|
|
103
120
|
const fs = require('fs');
|
|
104
121
|
const configPath = options.tsconfig || 'tsconfig.json';
|
|
105
122
|
if (!fs.existsSync(configPath)) {
|
|
106
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(
|
|
123
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red('✖')} TypeScript config not found: ${configPath}`, 'error');
|
|
107
124
|
process.exit(1);
|
|
108
125
|
}
|
|
109
126
|
try {
|
|
110
127
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
111
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(
|
|
112
|
-
if (config.compilerOptions) {
|
|
113
|
-
|
|
114
|
-
logger_manager_js_1.loggerManager.printLine(
|
|
115
|
-
logger_manager_js_1.loggerManager.printLine(`
|
|
116
|
-
logger_manager_js_1.loggerManager.printLine(`
|
|
117
|
-
logger_manager_js_1.loggerManager.printLine(`
|
|
128
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green('✓')} TypeScript config is valid`, 'info');
|
|
129
|
+
if (config.compilerOptions && !options.quiet) {
|
|
130
|
+
const opts = config.compilerOptions;
|
|
131
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim('Configuration:')}`, 'info');
|
|
132
|
+
logger_manager_js_1.loggerManager.printLine(` Target: ${opts.target || 'ES5'}`, 'info');
|
|
133
|
+
logger_manager_js_1.loggerManager.printLine(` Module: ${opts.module || 'CommonJS'}`, 'info');
|
|
134
|
+
logger_manager_js_1.loggerManager.printLine(` Strict: ${opts.strict || false}`, 'info');
|
|
135
|
+
logger_manager_js_1.loggerManager.printLine(` Source Maps: ${opts.sourceMap || false}`, 'info');
|
|
136
|
+
logger_manager_js_1.loggerManager.printLine(` Skip Lib Check: ${opts.skipLibCheck || false}`, 'info');
|
|
118
137
|
}
|
|
119
138
|
}
|
|
120
139
|
catch (error) {
|
|
121
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(
|
|
140
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red('✖')} Invalid TypeScript config: ${error.message}`, 'error');
|
|
122
141
|
process.exit(1);
|
|
123
142
|
}
|
|
124
143
|
});
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
144
|
+
// Performance info command
|
|
145
|
+
program
|
|
146
|
+
.command('dev:info')
|
|
147
|
+
.description('Show development server information')
|
|
148
|
+
.action(() => {
|
|
149
|
+
const path = require('path');
|
|
150
|
+
const fs = require('fs');
|
|
151
|
+
const os = require('os');
|
|
152
|
+
console.log('');
|
|
153
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue('⚡')} ${chalk_1.default.bold('neex dev')} - Development Server Info`, 'info');
|
|
154
|
+
console.log('');
|
|
155
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim('System:')}`, 'info');
|
|
156
|
+
logger_manager_js_1.loggerManager.printLine(` Platform: ${os.platform()} ${os.arch()}`, 'info');
|
|
157
|
+
logger_manager_js_1.loggerManager.printLine(` Node.js: ${process.version}`, 'info');
|
|
158
|
+
logger_manager_js_1.loggerManager.printLine(` Memory: ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB used`, 'info');
|
|
159
|
+
console.log('');
|
|
160
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim('Features:')}`, 'info');
|
|
161
|
+
logger_manager_js_1.loggerManager.printLine(` ${chalk_1.default.green('✓')} Ultra-fast TypeScript compilation`, 'info');
|
|
162
|
+
logger_manager_js_1.loggerManager.printLine(` ${chalk_1.default.green('✓')} Intelligent module caching`, 'info');
|
|
163
|
+
logger_manager_js_1.loggerManager.printLine(` ${chalk_1.default.green('✓')} Hot reload with dependency tracking`, 'info');
|
|
164
|
+
logger_manager_js_1.loggerManager.printLine(` ${chalk_1.default.green('✓')} Source map support`, 'info');
|
|
165
|
+
logger_manager_js_1.loggerManager.printLine(` ${chalk_1.default.green('✓')} Memory-optimized processing`, 'info');
|
|
166
|
+
const tsConfigExists = fs.existsSync('tsconfig.json');
|
|
167
|
+
const packageJsonExists = fs.existsSync('package.json');
|
|
168
|
+
console.log('');
|
|
169
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim('Project:')}`, 'info');
|
|
170
|
+
logger_manager_js_1.loggerManager.printLine(` TypeScript Config: ${tsConfigExists ? chalk_1.default.green('✓') : chalk_1.default.red('✖')}`, 'info');
|
|
171
|
+
logger_manager_js_1.loggerManager.printLine(` Package.json: ${packageJsonExists ? chalk_1.default.green('✓') : chalk_1.default.red('✖')}`, 'info');
|
|
172
|
+
if (packageJsonExists) {
|
|
173
|
+
try {
|
|
174
|
+
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
|
175
|
+
if (pkg.name) {
|
|
176
|
+
logger_manager_js_1.loggerManager.printLine(` Name: ${pkg.name}`, 'info');
|
|
177
|
+
}
|
|
178
|
+
if (pkg.version) {
|
|
179
|
+
logger_manager_js_1.loggerManager.printLine(` Version: ${pkg.version}`, 'info');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
// Ignore package.json parsing errors
|
|
184
|
+
}
|
|
145
185
|
}
|
|
186
|
+
console.log('');
|
|
146
187
|
});
|
|
188
|
+
// Cleanup function is no longer needed here as it's handled within the command
|
|
189
|
+
const cleanupDev = () => { };
|
|
147
190
|
return { cleanupDev };
|
|
148
191
|
}
|
|
149
192
|
exports.addDevCommands = addDevCommands;
|
|
@@ -130,6 +130,20 @@ function addStartCommands(program) {
|
|
|
130
130
|
inspectBrk: options.inspectBrk,
|
|
131
131
|
nodeArgs: options.nodeArgs
|
|
132
132
|
});
|
|
133
|
+
// --- Signal Handlers for Start ---
|
|
134
|
+
const cleanupAndExit = (signal) => {
|
|
135
|
+
if (startManager) {
|
|
136
|
+
logger_manager_js_1.loggerManager.printLine(`\n${chalk_1.default.yellow('⏹')} Received ${signal}, shutting down...`, 'info');
|
|
137
|
+
startManager.stop().then(() => process.exit(0));
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
process.exit(0);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
const sigintHandler = () => cleanupAndExit('SIGINT');
|
|
144
|
+
const sigtermHandler = () => cleanupAndExit('SIGTERM');
|
|
145
|
+
process.on('SIGINT', sigintHandler);
|
|
146
|
+
process.on('SIGTERM', sigtermHandler);
|
|
133
147
|
await startManager.start();
|
|
134
148
|
}
|
|
135
149
|
catch (error) {
|
|
@@ -142,49 +156,8 @@ function addStartCommands(program) {
|
|
|
142
156
|
process.exit(1);
|
|
143
157
|
}
|
|
144
158
|
});
|
|
145
|
-
// Cleanup function
|
|
146
|
-
const cleanupStart = async () => {
|
|
147
|
-
if (startManager) {
|
|
148
|
-
try {
|
|
149
|
-
await startManager.stop();
|
|
150
|
-
startManager = null;
|
|
151
|
-
}
|
|
152
|
-
catch (error) {
|
|
153
|
-
if (process.env.VERBOSE) {
|
|
154
|
-
console.error('Cleanup error:', error);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
// Signal handling
|
|
160
|
-
const handleExit = (signal) => {
|
|
161
|
-
if (startManager) {
|
|
162
|
-
console.log(`\n${chalk_1.default.yellow(figures_1.default.warning)} Received ${signal}, shutting down gracefully...`);
|
|
163
|
-
cleanupStart().then(() => {
|
|
164
|
-
process.exit(0);
|
|
165
|
-
}).catch(() => {
|
|
166
|
-
process.exit(1);
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
process.exit(0);
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
process.on('SIGINT', () => handleExit('SIGINT'));
|
|
174
|
-
process.on('SIGTERM', () => handleExit('SIGTERM'));
|
|
175
|
-
process.on('SIGUSR2', () => handleExit('SIGUSR2'));
|
|
176
|
-
process.on('uncaughtException', (error) => {
|
|
177
|
-
console.error(`${chalk_1.default.red(figures_1.default.cross)} Uncaught Exception:`, error);
|
|
178
|
-
cleanupStart().then(() => {
|
|
179
|
-
process.exit(1);
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
process.on('unhandledRejection', (reason, promise) => {
|
|
183
|
-
console.error(`${chalk_1.default.red(figures_1.default.cross)} Unhandled Rejection at:`, promise, 'reason:', reason);
|
|
184
|
-
cleanupStart().then(() => {
|
|
185
|
-
process.exit(1);
|
|
186
|
-
});
|
|
187
|
-
});
|
|
159
|
+
// Cleanup function is no longer needed here as it's handled within the command
|
|
160
|
+
const cleanupStart = async () => { };
|
|
188
161
|
return { cleanupStart };
|
|
189
162
|
}
|
|
190
163
|
exports.addStartCommands = addStartCommands;
|
package/dist/src/dev-manager.js
CHANGED
|
@@ -27,7 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
exports.DevManager = void 0;
|
|
30
|
-
// src/dev-manager.ts -
|
|
30
|
+
// src/dev-manager.ts - Ultra-fast TypeScript development server like tsx
|
|
31
31
|
const child_process_1 = require("child_process");
|
|
32
32
|
const chokidar_1 = require("chokidar");
|
|
33
33
|
const logger_manager_js_1 = require("./logger-manager.js");
|
|
@@ -37,6 +37,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
37
37
|
const fs_1 = __importDefault(require("fs"));
|
|
38
38
|
const lodash_1 = require("lodash");
|
|
39
39
|
const ts = __importStar(require("typescript"));
|
|
40
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
40
41
|
class DevManager {
|
|
41
42
|
constructor(options) {
|
|
42
43
|
this.process = null;
|
|
@@ -45,10 +46,23 @@ class DevManager {
|
|
|
45
46
|
this.restartCount = 0;
|
|
46
47
|
this.startTime = null;
|
|
47
48
|
this.moduleCache = new Map();
|
|
48
|
-
this.
|
|
49
|
+
this.currentTempFile = null;
|
|
49
50
|
this.options = options;
|
|
50
|
-
this.
|
|
51
|
+
this.tempDir = path_1.default.join(process.cwd(), '.neex-temp');
|
|
52
|
+
this.debouncedRestart = (0, lodash_1.debounce)(this.restart.bind(this), Math.max(options.delay, 100));
|
|
51
53
|
this.tsCompilerOptions = this.loadTsConfig();
|
|
54
|
+
this.setupTempDir();
|
|
55
|
+
}
|
|
56
|
+
setupTempDir() {
|
|
57
|
+
if (fs_1.default.existsSync(this.tempDir)) {
|
|
58
|
+
try {
|
|
59
|
+
fs_1.default.rmSync(this.tempDir, { recursive: true, force: true });
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// Ignore cleanup errors
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
fs_1.default.mkdirSync(this.tempDir, { recursive: true });
|
|
52
66
|
}
|
|
53
67
|
loadTsConfig() {
|
|
54
68
|
const configPath = this.options.tsConfig || 'tsconfig.json';
|
|
@@ -57,8 +71,6 @@ class DevManager {
|
|
|
57
71
|
module: ts.ModuleKind.CommonJS,
|
|
58
72
|
moduleResolution: ts.ModuleResolutionKind.NodeJs,
|
|
59
73
|
allowJs: true,
|
|
60
|
-
outDir: undefined,
|
|
61
|
-
rootDir: undefined,
|
|
62
74
|
strict: false,
|
|
63
75
|
esModuleInterop: true,
|
|
64
76
|
skipLibCheck: true,
|
|
@@ -68,221 +80,222 @@ class DevManager {
|
|
|
68
80
|
sourceMap: this.options.sourceMaps,
|
|
69
81
|
inlineSourceMap: false,
|
|
70
82
|
inlineSources: false,
|
|
83
|
+
removeComments: false,
|
|
84
|
+
preserveConstEnums: false,
|
|
85
|
+
isolatedModules: true, // For faster compilation
|
|
71
86
|
};
|
|
72
87
|
if (fs_1.default.existsSync(configPath)) {
|
|
73
88
|
try {
|
|
74
89
|
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
75
|
-
if (configFile.error) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (parsedConfig.errors.length > 0) {
|
|
81
|
-
logger_manager_js_1.loggerManager.printLine(`Error parsing tsconfig.json: ${parsedConfig.errors[0].messageText}`, 'warn');
|
|
82
|
-
return defaultOptions;
|
|
83
|
-
}
|
|
84
|
-
// Override some options for development
|
|
85
|
-
const options = { ...parsedConfig.options, ...defaultOptions };
|
|
86
|
-
if (this.options.verbose) {
|
|
87
|
-
logger_manager_js_1.loggerManager.printLine(`Loaded TypeScript config from ${configPath}`, 'info');
|
|
90
|
+
if (!configFile.error) {
|
|
91
|
+
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path_1.default.dirname(configPath));
|
|
92
|
+
if (parsedConfig.errors.length === 0) {
|
|
93
|
+
return { ...defaultOptions, ...parsedConfig.options };
|
|
94
|
+
}
|
|
88
95
|
}
|
|
89
|
-
return options;
|
|
90
96
|
}
|
|
91
97
|
catch (error) {
|
|
92
|
-
|
|
98
|
+
// Fall back to defaults
|
|
93
99
|
}
|
|
94
100
|
}
|
|
95
101
|
return defaultOptions;
|
|
96
102
|
}
|
|
97
103
|
loadEnvFile() {
|
|
98
|
-
|
|
104
|
+
let count = 0;
|
|
105
|
+
const envFile = this.options.envFile;
|
|
106
|
+
if (envFile && fs_1.default.existsSync(envFile)) {
|
|
99
107
|
try {
|
|
100
|
-
const envContent = fs_1.default.readFileSync(
|
|
108
|
+
const envContent = fs_1.default.readFileSync(envFile, 'utf8');
|
|
101
109
|
const lines = envContent.split('\n');
|
|
102
|
-
let loadedCount = 0;
|
|
103
110
|
for (const line of lines) {
|
|
104
111
|
const trimmed = line.trim();
|
|
105
112
|
if (trimmed && !trimmed.startsWith('#')) {
|
|
106
113
|
const [key, ...values] = trimmed.split('=');
|
|
107
114
|
if (key && values.length > 0) {
|
|
108
115
|
process.env[key.trim()] = values.join('=').trim().replace(/^["']|["']$/g, '');
|
|
109
|
-
|
|
116
|
+
count++;
|
|
110
117
|
}
|
|
111
118
|
}
|
|
112
119
|
}
|
|
113
|
-
if (!this.options.quiet
|
|
114
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.
|
|
115
|
-
}
|
|
116
|
-
else if (this.options.verbose) {
|
|
117
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim(figures_1.default.info)} No env variables found in ${this.options.envFile}`, 'info');
|
|
120
|
+
if (!this.options.quiet) {
|
|
121
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue(figures_1.default.info)} Loaded ${count} env variables from ${envFile}`, 'info');
|
|
118
122
|
}
|
|
119
123
|
}
|
|
120
124
|
catch (error) {
|
|
121
|
-
|
|
125
|
+
if (this.options.verbose) {
|
|
126
|
+
logger_manager_js_1.loggerManager.printLine(`Failed to load ${envFile}: ${error.message}`, 'warn');
|
|
127
|
+
}
|
|
122
128
|
}
|
|
123
129
|
}
|
|
124
130
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (this.options.transpileOnly) {
|
|
146
|
-
// Fast transpile without type checking
|
|
147
|
-
result = ts.transpileModule(sourceCode, {
|
|
148
|
-
compilerOptions: this.tsCompilerOptions,
|
|
149
|
-
fileName: absolutePath,
|
|
150
|
-
reportDiagnostics: false
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
// Full compilation with type checking
|
|
155
|
-
const program = ts.createProgram([absolutePath], this.tsCompilerOptions);
|
|
156
|
-
const sourceFile = program.getSourceFile(absolutePath);
|
|
157
|
-
if (!sourceFile) {
|
|
158
|
-
throw new Error(`Could not load source file: ${absolutePath}`);
|
|
131
|
+
createHash(content) {
|
|
132
|
+
return crypto_1.default.createHash('md5').update(content).digest('hex');
|
|
133
|
+
}
|
|
134
|
+
extractDependencies(sourceCode, filePath) {
|
|
135
|
+
const dependencies = [];
|
|
136
|
+
const importRegex = /(?:import|require)\s*(?:\([^)]*\)|[^;]+?from\s+)?['"`]([^'"`]+)['"`]/g;
|
|
137
|
+
let match;
|
|
138
|
+
while ((match = importRegex.exec(sourceCode)) !== null) {
|
|
139
|
+
const importPath = match[1];
|
|
140
|
+
if (importPath.startsWith('.')) {
|
|
141
|
+
let resolvedPath = path_1.default.resolve(path_1.default.dirname(filePath), importPath);
|
|
142
|
+
// Try to resolve with extensions
|
|
143
|
+
if (!fs_1.default.existsSync(resolvedPath)) {
|
|
144
|
+
for (const ext of ['.ts', '.tsx', '.js', '.jsx']) {
|
|
145
|
+
const withExt = resolvedPath + ext;
|
|
146
|
+
if (fs_1.default.existsSync(withExt)) {
|
|
147
|
+
resolvedPath = withExt;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
159
151
|
}
|
|
160
|
-
//
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return `${path_1.default.relative(process.cwd(), diagnostic.file.fileName)}:${line + 1}:${character + 1} - ${message}`;
|
|
152
|
+
// Try index files
|
|
153
|
+
if (!fs_1.default.existsSync(resolvedPath)) {
|
|
154
|
+
for (const ext of ['.ts', '.tsx', '.js', '.jsx']) {
|
|
155
|
+
const indexPath = path_1.default.join(resolvedPath, 'index' + ext);
|
|
156
|
+
if (fs_1.default.existsSync(indexPath)) {
|
|
157
|
+
resolvedPath = indexPath;
|
|
158
|
+
break;
|
|
168
159
|
}
|
|
169
|
-
return message;
|
|
170
|
-
});
|
|
171
|
-
logger_manager_js_1.loggerManager.printLine(`TypeScript compilation errors:\n${errors.join('\n')}`, 'error');
|
|
172
|
-
if (!this.options.quiet) {
|
|
173
|
-
process.exit(1);
|
|
174
160
|
}
|
|
175
161
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
reportDiagnostics: true
|
|
180
|
-
});
|
|
162
|
+
if (fs_1.default.existsSync(resolvedPath)) {
|
|
163
|
+
dependencies.push(resolvedPath);
|
|
164
|
+
}
|
|
181
165
|
}
|
|
182
|
-
|
|
166
|
+
}
|
|
167
|
+
return dependencies;
|
|
168
|
+
}
|
|
169
|
+
compileModule(filePath, forceRecompile = false) {
|
|
170
|
+
const absolutePath = path_1.default.resolve(filePath);
|
|
171
|
+
try {
|
|
172
|
+
const sourceCode = fs_1.default.readFileSync(absolutePath, 'utf8');
|
|
173
|
+
const hash = this.createHash(sourceCode);
|
|
174
|
+
const cached = this.moduleCache.get(absolutePath);
|
|
175
|
+
// Check if we can use cached version
|
|
176
|
+
if (!forceRecompile && cached && cached.hash === hash) {
|
|
177
|
+
return cached;
|
|
178
|
+
}
|
|
179
|
+
const dependencies = this.extractDependencies(sourceCode, absolutePath);
|
|
180
|
+
// Fast transpile without type checking for development
|
|
181
|
+
const result = ts.transpileModule(sourceCode, {
|
|
182
|
+
compilerOptions: this.tsCompilerOptions,
|
|
183
|
+
fileName: absolutePath,
|
|
184
|
+
reportDiagnostics: false // Skip diagnostics for speed
|
|
185
|
+
});
|
|
186
|
+
const moduleInfo = {
|
|
183
187
|
code: result.outputText,
|
|
184
188
|
map: result.sourceMapText,
|
|
189
|
+
hash,
|
|
190
|
+
timestamp: Date.now(),
|
|
185
191
|
dependencies
|
|
186
192
|
};
|
|
187
|
-
this.moduleCache.set(absolutePath,
|
|
188
|
-
|
|
193
|
+
this.moduleCache.set(absolutePath, moduleInfo);
|
|
194
|
+
if (this.options.verbose) {
|
|
195
|
+
logger_manager_js_1.loggerManager.printLine(`Compiled ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
|
|
196
|
+
}
|
|
197
|
+
return moduleInfo;
|
|
189
198
|
}
|
|
190
199
|
catch (error) {
|
|
191
|
-
logger_manager_js_1.loggerManager.printLine(`Compilation error
|
|
200
|
+
logger_manager_js_1.loggerManager.printLine(`Compilation error: ${error.message}`, 'error');
|
|
192
201
|
throw error;
|
|
193
202
|
}
|
|
194
203
|
}
|
|
195
|
-
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
204
|
+
invalidateModuleCache(filePath) {
|
|
205
|
+
const absolutePath = path_1.default.resolve(filePath);
|
|
206
|
+
// Remove the file itself
|
|
207
|
+
this.moduleCache.delete(absolutePath);
|
|
208
|
+
// Remove any modules that depend on this file
|
|
209
|
+
const toRemove = [];
|
|
210
|
+
for (const [cachedPath, info] of this.moduleCache.entries()) {
|
|
211
|
+
if (info.dependencies.includes(absolutePath)) {
|
|
212
|
+
toRemove.push(cachedPath);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
for (const pathToRemove of toRemove) {
|
|
216
|
+
this.moduleCache.delete(pathToRemove);
|
|
199
217
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
218
|
+
if (this.options.verbose && toRemove.length > 0) {
|
|
219
|
+
logger_manager_js_1.loggerManager.printLine(`Invalidated ${toRemove.length + 1} modules`, 'info');
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
createExecutableFile() {
|
|
223
|
+
// Always force recompile the main file
|
|
224
|
+
const mainModule = this.compileModule(this.options.file, true);
|
|
225
|
+
// Create a unique temp file
|
|
226
|
+
const timestamp = Date.now();
|
|
227
|
+
const random = Math.random().toString(36).substr(2, 9);
|
|
228
|
+
const tempFile = path_1.default.join(this.tempDir, `main-${timestamp}-${random}.js`);
|
|
229
|
+
let code = mainModule.code;
|
|
230
|
+
// Add source map support
|
|
231
|
+
if (mainModule.map && this.options.sourceMaps) {
|
|
204
232
|
const mapFile = tempFile + '.map';
|
|
205
|
-
fs_1.default.writeFileSync(mapFile,
|
|
233
|
+
fs_1.default.writeFileSync(mapFile, mainModule.map);
|
|
206
234
|
code += `\n//# sourceMappingURL=${path_1.default.basename(mapFile)}`;
|
|
207
235
|
}
|
|
208
236
|
fs_1.default.writeFileSync(tempFile, code);
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
cleanupTempFiles() {
|
|
212
|
-
const tempDir = path_1.default.join(process.cwd(), '.neex-temp');
|
|
213
|
-
if (fs_1.default.existsSync(tempDir)) {
|
|
237
|
+
// Clean up old temp file
|
|
238
|
+
if (this.currentTempFile && fs_1.default.existsSync(this.currentTempFile)) {
|
|
214
239
|
try {
|
|
215
|
-
fs_1.default.
|
|
240
|
+
fs_1.default.unlinkSync(this.currentTempFile);
|
|
241
|
+
const mapFile = this.currentTempFile + '.map';
|
|
242
|
+
if (fs_1.default.existsSync(mapFile)) {
|
|
243
|
+
fs_1.default.unlinkSync(mapFile);
|
|
244
|
+
}
|
|
216
245
|
}
|
|
217
246
|
catch (error) {
|
|
218
247
|
// Ignore cleanup errors
|
|
219
248
|
}
|
|
220
249
|
}
|
|
250
|
+
this.currentTempFile = tempFile;
|
|
251
|
+
return tempFile;
|
|
221
252
|
}
|
|
222
253
|
async getExecuteCommand() {
|
|
223
254
|
if (this.options.execCommand) {
|
|
224
255
|
const parts = this.options.execCommand.split(' ');
|
|
225
|
-
return { command: parts[0], args:
|
|
256
|
+
return { command: parts[0], args: parts.slice(1) };
|
|
226
257
|
}
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (this.options.inspect) {
|
|
258
|
+
const executableFile = this.createExecutableFile();
|
|
259
|
+
const args = [...this.options.nodeArgs, executableFile];
|
|
260
|
+
// Add Node.js flags
|
|
261
|
+
if (this.options.inspect)
|
|
232
262
|
args.unshift('--inspect');
|
|
233
|
-
|
|
234
|
-
if (this.options.inspectBrk) {
|
|
263
|
+
if (this.options.inspectBrk)
|
|
235
264
|
args.unshift('--inspect-brk');
|
|
236
|
-
|
|
237
|
-
// Enable source map support
|
|
238
|
-
if (this.options.sourceMaps) {
|
|
265
|
+
if (this.options.sourceMaps)
|
|
239
266
|
args.unshift('--enable-source-maps');
|
|
240
|
-
}
|
|
241
267
|
return { command: 'node', args };
|
|
242
268
|
}
|
|
243
269
|
clearConsole() {
|
|
244
270
|
if (this.options.clearConsole && process.stdout.isTTY) {
|
|
245
|
-
process.stdout.write('\
|
|
271
|
+
process.stdout.write('\x1Bc'); // Clear screen and scrollback
|
|
246
272
|
}
|
|
247
273
|
}
|
|
248
274
|
async startProcess() {
|
|
249
275
|
var _a, _b;
|
|
250
|
-
if (this.process)
|
|
276
|
+
if (this.process)
|
|
251
277
|
return;
|
|
252
|
-
}
|
|
253
278
|
this.loadEnvFile();
|
|
254
279
|
try {
|
|
255
280
|
const { command, args } = await this.getExecuteCommand();
|
|
256
|
-
if (this.options.verbose) {
|
|
257
|
-
logger_manager_js_1.loggerManager.printLine(`Executing: ${command} ${args.join(' ')}`, 'info');
|
|
258
|
-
}
|
|
259
281
|
this.process = (0, child_process_1.spawn)(command, args, {
|
|
260
282
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
261
|
-
shell: false,
|
|
262
283
|
env: {
|
|
263
284
|
...process.env,
|
|
264
285
|
NODE_ENV: process.env.NODE_ENV || 'development',
|
|
265
286
|
FORCE_COLOR: this.options.color ? '1' : '0',
|
|
266
|
-
|
|
267
|
-
NEEX_DEV: '1'
|
|
287
|
+
NODE_OPTIONS: '--max-old-space-size=4096', // Prevent memory issues
|
|
268
288
|
},
|
|
269
|
-
detached:
|
|
289
|
+
detached: false // Keep attached for better cleanup
|
|
270
290
|
});
|
|
271
291
|
this.startTime = new Date();
|
|
272
292
|
this.restartCount++;
|
|
273
|
-
|
|
274
|
-
const timestamp = new Date().toLocaleTimeString();
|
|
275
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.play)} Started ${chalk_1.default.cyan(path_1.default.relative(process.cwd(), this.options.file))} ${chalk_1.default.dim(`(${timestamp})`)}`, 'info');
|
|
276
|
-
}
|
|
293
|
+
// Handle stdout/stderr
|
|
277
294
|
(_a = this.process.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
|
|
278
|
-
|
|
279
|
-
process.stdout.write(data);
|
|
280
|
-
}
|
|
295
|
+
process.stdout.write(data);
|
|
281
296
|
});
|
|
282
297
|
(_b = this.process.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
|
|
283
|
-
|
|
284
|
-
process.stderr.write(data);
|
|
285
|
-
}
|
|
298
|
+
process.stderr.write(data);
|
|
286
299
|
});
|
|
287
300
|
this.process.on('error', (error) => {
|
|
288
301
|
logger_manager_js_1.loggerManager.printLine(`Process error: ${error.message}`, 'error');
|
|
@@ -290,177 +303,147 @@ class DevManager {
|
|
|
290
303
|
this.process.on('exit', (code, signal) => {
|
|
291
304
|
if (this.process) {
|
|
292
305
|
this.process = null;
|
|
293
|
-
if (!this.isRestarting) {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Process exited with code ${code} after ${duration}ms`, 'error');
|
|
297
|
-
}
|
|
306
|
+
if (!this.isRestarting && code !== 0) {
|
|
307
|
+
const duration = this.startTime ? Date.now() - this.startTime.getTime() : 0;
|
|
308
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red('✖')} Process exited with code ${code} (${duration}ms)`, 'error');
|
|
298
309
|
}
|
|
299
310
|
}
|
|
300
311
|
});
|
|
301
312
|
}
|
|
302
313
|
catch (error) {
|
|
303
|
-
logger_manager_js_1.loggerManager.printLine(`Failed to start
|
|
314
|
+
logger_manager_js_1.loggerManager.printLine(`Failed to start: ${error.message}`, 'error');
|
|
304
315
|
throw error;
|
|
305
316
|
}
|
|
306
317
|
}
|
|
307
318
|
async stopProcess() {
|
|
308
|
-
if (!this.process)
|
|
319
|
+
if (!this.process)
|
|
309
320
|
return;
|
|
310
|
-
}
|
|
311
321
|
return new Promise((resolve) => {
|
|
312
|
-
if (!this.process) {
|
|
313
|
-
resolve();
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
322
|
const proc = this.process;
|
|
317
323
|
this.process = null;
|
|
318
324
|
const cleanup = () => {
|
|
319
|
-
if (!this.options.quiet) {
|
|
320
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow(figures_1.default.square)} Stopped process`, 'info');
|
|
321
|
-
}
|
|
322
|
-
this.cleanupTempFiles();
|
|
323
325
|
resolve();
|
|
324
326
|
};
|
|
325
327
|
proc.on('exit', cleanup);
|
|
326
328
|
proc.on('error', cleanup);
|
|
327
329
|
try {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
process.kill(-proc.pid, 'SIGKILL');
|
|
336
|
-
}
|
|
337
|
-
catch (e) {
|
|
338
|
-
// Ignore
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}, 3000);
|
|
342
|
-
}
|
|
330
|
+
proc.kill('SIGTERM');
|
|
331
|
+
// Force kill after timeout
|
|
332
|
+
setTimeout(() => {
|
|
333
|
+
if (!proc.killed) {
|
|
334
|
+
proc.kill('SIGKILL');
|
|
335
|
+
}
|
|
336
|
+
}, 1000);
|
|
343
337
|
}
|
|
344
338
|
catch (error) {
|
|
345
|
-
// Process might already be dead
|
|
346
339
|
cleanup();
|
|
347
340
|
}
|
|
348
341
|
});
|
|
349
342
|
}
|
|
350
|
-
invalidateCache(filePath) {
|
|
351
|
-
const absolutePath = path_1.default.resolve(filePath);
|
|
352
|
-
// Remove from cache
|
|
353
|
-
this.moduleCache.delete(absolutePath);
|
|
354
|
-
// Remove dependent modules from cache
|
|
355
|
-
for (const [cachedPath, module] of this.moduleCache.entries()) {
|
|
356
|
-
if (module.dependencies.has(absolutePath)) {
|
|
357
|
-
this.moduleCache.delete(cachedPath);
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
343
|
async restart() {
|
|
362
|
-
if (this.isRestarting)
|
|
344
|
+
if (this.isRestarting)
|
|
363
345
|
return;
|
|
364
|
-
}
|
|
365
346
|
this.isRestarting = true;
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
}
|
|
347
|
+
// Clear console immediately for better UX
|
|
348
|
+
this.clearConsole();
|
|
369
349
|
if (!this.options.quiet) {
|
|
370
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow(
|
|
350
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow('⟳')} Restarting...`, 'info');
|
|
371
351
|
}
|
|
372
|
-
//
|
|
373
|
-
this.moduleCache.clear();
|
|
352
|
+
// Stop current process
|
|
374
353
|
await this.stopProcess();
|
|
375
|
-
//
|
|
376
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
354
|
+
// Start new process
|
|
377
355
|
await this.startProcess();
|
|
378
356
|
this.isRestarting = false;
|
|
379
357
|
}
|
|
380
358
|
setupWatcher() {
|
|
381
359
|
const watchPatterns = this.options.watch;
|
|
360
|
+
// Optimized ignore patterns
|
|
382
361
|
const ignored = [
|
|
383
|
-
'
|
|
384
|
-
'
|
|
385
|
-
'
|
|
386
|
-
'
|
|
387
|
-
'
|
|
362
|
+
'node_modules/**',
|
|
363
|
+
'.git/**',
|
|
364
|
+
'dist/**',
|
|
365
|
+
'build/**',
|
|
366
|
+
'.neex-temp/**',
|
|
388
367
|
'**/*.log',
|
|
389
368
|
'**/*.d.ts',
|
|
390
|
-
|
|
369
|
+
'**/*.map',
|
|
370
|
+
'**/*.tsbuildinfo',
|
|
371
|
+
...this.options.ignore
|
|
391
372
|
];
|
|
392
373
|
this.watcher = (0, chokidar_1.watch)(watchPatterns, {
|
|
393
374
|
ignored,
|
|
394
375
|
ignoreInitial: true,
|
|
395
376
|
followSymlinks: false,
|
|
396
377
|
usePolling: false,
|
|
397
|
-
atomic:
|
|
378
|
+
atomic: 50,
|
|
398
379
|
awaitWriteFinish: {
|
|
399
380
|
stabilityThreshold: 100,
|
|
400
381
|
pollInterval: 50
|
|
401
382
|
}
|
|
402
383
|
});
|
|
403
384
|
this.watcher.on('change', (filePath) => {
|
|
404
|
-
this.
|
|
385
|
+
this.invalidateModuleCache(filePath);
|
|
405
386
|
if (this.options.verbose) {
|
|
406
|
-
logger_manager_js_1.loggerManager.printLine(
|
|
387
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue('●')} ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
|
|
407
388
|
}
|
|
408
389
|
this.debouncedRestart();
|
|
409
390
|
});
|
|
410
391
|
this.watcher.on('add', (filePath) => {
|
|
411
392
|
if (this.options.verbose) {
|
|
412
|
-
logger_manager_js_1.loggerManager.printLine(
|
|
393
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green('+')} ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
|
|
413
394
|
}
|
|
414
395
|
this.debouncedRestart();
|
|
415
396
|
});
|
|
416
397
|
this.watcher.on('unlink', (filePath) => {
|
|
417
|
-
this.
|
|
398
|
+
this.invalidateModuleCache(filePath);
|
|
418
399
|
if (this.options.verbose) {
|
|
419
|
-
logger_manager_js_1.loggerManager.printLine(
|
|
400
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red('-')} ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
|
|
420
401
|
}
|
|
421
402
|
this.debouncedRestart();
|
|
422
403
|
});
|
|
423
404
|
this.watcher.on('error', (error) => {
|
|
424
405
|
logger_manager_js_1.loggerManager.printLine(`Watcher error: ${error.message}`, 'error');
|
|
425
406
|
});
|
|
426
|
-
if (this.options.verbose) {
|
|
427
|
-
logger_manager_js_1.loggerManager.printLine(`Watching: ${watchPatterns.join(', ')}`, 'info');
|
|
428
|
-
logger_manager_js_1.loggerManager.printLine(`Ignoring: ${ignored.join(', ')}`, 'info');
|
|
429
|
-
}
|
|
430
407
|
}
|
|
431
408
|
async start() {
|
|
432
|
-
// Check if target file exists
|
|
433
409
|
if (!fs_1.default.existsSync(this.options.file)) {
|
|
434
410
|
throw new Error(`Target file not found: ${this.options.file}`);
|
|
435
411
|
}
|
|
436
|
-
// Validate TypeScript file
|
|
437
412
|
const ext = path_1.default.extname(this.options.file);
|
|
438
413
|
if (!['.ts', '.tsx', '.js', '.jsx'].includes(ext)) {
|
|
439
414
|
throw new Error(`Unsupported file extension: ${ext}`);
|
|
440
415
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
logger_manager_js_1.loggerManager.printLine(
|
|
446
|
-
logger_manager_js_1.loggerManager.printLine(`Restart delay: ${this.options.delay}ms`, 'info');
|
|
447
|
-
logger_manager_js_1.loggerManager.printLine(`Transpile only: ${this.options.transpileOnly}`, 'info');
|
|
448
|
-
logger_manager_js_1.loggerManager.printLine(`Source maps: ${this.options.sourceMaps}`, 'info');
|
|
416
|
+
// Clear any existing cache
|
|
417
|
+
this.moduleCache.clear();
|
|
418
|
+
this.setupTempDir();
|
|
419
|
+
if (!this.options.quiet) {
|
|
420
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue('ℹ')} Starting TypeScript development server...`, 'info');
|
|
449
421
|
}
|
|
450
422
|
this.setupWatcher();
|
|
451
423
|
await this.startProcess();
|
|
452
|
-
|
|
424
|
+
if (!this.options.quiet) {
|
|
425
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green('✓')} Watching for changes...`, 'info');
|
|
426
|
+
}
|
|
453
427
|
}
|
|
454
428
|
async stop() {
|
|
455
|
-
|
|
429
|
+
if (!this.options.quiet) {
|
|
430
|
+
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow('⏹')} Stopping dev server...`, 'info');
|
|
431
|
+
}
|
|
456
432
|
if (this.watcher) {
|
|
457
433
|
await this.watcher.close();
|
|
458
434
|
this.watcher = null;
|
|
459
435
|
}
|
|
460
436
|
await this.stopProcess();
|
|
461
|
-
|
|
462
|
-
|
|
437
|
+
// Cleanup temp files
|
|
438
|
+
if (fs_1.default.existsSync(this.tempDir)) {
|
|
439
|
+
try {
|
|
440
|
+
fs_1.default.rmSync(this.tempDir, { recursive: true, force: true });
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
// Ignore cleanup errors
|
|
444
|
+
}
|
|
463
445
|
}
|
|
446
|
+
this.moduleCache.clear();
|
|
464
447
|
}
|
|
465
448
|
}
|
|
466
449
|
exports.DevManager = DevManager;
|
|
@@ -442,7 +442,7 @@ class StartManager {
|
|
|
442
442
|
if (this.isShuttingDown)
|
|
443
443
|
return;
|
|
444
444
|
this.isShuttingDown = true;
|
|
445
|
-
this.log('Shutting down gracefully
|
|
445
|
+
this.log(`${chalk_1.default.yellow('⏹')} Shutting down gracefully...`);
|
|
446
446
|
if (this.watcher) {
|
|
447
447
|
await this.watcher.close();
|
|
448
448
|
}
|
|
@@ -474,7 +474,7 @@ class StartManager {
|
|
|
474
474
|
}
|
|
475
475
|
await Promise.allSettled(shutdownPromises);
|
|
476
476
|
this.workers.clear();
|
|
477
|
-
this.log('Server stopped
|
|
477
|
+
this.log(`${chalk_1.default.green('⏹')} Server stopped.`);
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
480
|
exports.StartManager = StartManager;
|