neex 0.7.45 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +50 -326
  2. package/bin/neex +31 -0
  3. package/install.js +94 -0
  4. package/package.json +30 -63
  5. package/dist/bin/neex.d.ts +0 -26
  6. package/dist/bin/neex.d.ts.map +0 -1
  7. package/dist/bin/neex.js +0 -8
  8. package/dist/src/build-manager.d.ts +0 -41
  9. package/dist/src/build-manager.d.ts.map +0 -1
  10. package/dist/src/build-manager.js +0 -369
  11. package/dist/src/cli.d.ts +0 -2
  12. package/dist/src/cli.d.ts.map +0 -1
  13. package/dist/src/cli.js +0 -67
  14. package/dist/src/commands/add-commands.d.ts +0 -4
  15. package/dist/src/commands/add-commands.d.ts.map +0 -1
  16. package/dist/src/commands/add-commands.js +0 -83
  17. package/dist/src/commands/build-commands.d.ts +0 -5
  18. package/dist/src/commands/build-commands.d.ts.map +0 -1
  19. package/dist/src/commands/build-commands.js +0 -123
  20. package/dist/src/commands/dev-commands.d.ts +0 -5
  21. package/dist/src/commands/dev-commands.d.ts.map +0 -1
  22. package/dist/src/commands/dev-commands.js +0 -198
  23. package/dist/src/commands/index.d.ts +0 -8
  24. package/dist/src/commands/index.d.ts.map +0 -1
  25. package/dist/src/commands/index.js +0 -27
  26. package/dist/src/commands/init-commands.d.ts +0 -2
  27. package/dist/src/commands/init-commands.d.ts.map +0 -1
  28. package/dist/src/commands/init-commands.js +0 -20
  29. package/dist/src/commands/run-commands.d.ts +0 -3
  30. package/dist/src/commands/run-commands.d.ts.map +0 -1
  31. package/dist/src/commands/run-commands.js +0 -93
  32. package/dist/src/commands/server-commands.d.ts +0 -3
  33. package/dist/src/commands/server-commands.d.ts.map +0 -1
  34. package/dist/src/commands/server-commands.js +0 -51
  35. package/dist/src/commands/start-commands.d.ts +0 -5
  36. package/dist/src/commands/start-commands.d.ts.map +0 -1
  37. package/dist/src/commands/start-commands.js +0 -162
  38. package/dist/src/dev-manager.d.ts +0 -51
  39. package/dist/src/dev-manager.d.ts.map +0 -1
  40. package/dist/src/dev-manager.js +0 -471
  41. package/dist/src/index.d.ts +0 -41
  42. package/dist/src/index.d.ts.map +0 -1
  43. package/dist/src/index.js +0 -70
  44. package/dist/src/logger-manager.d.ts +0 -4
  45. package/dist/src/logger-manager.d.ts.map +0 -1
  46. package/dist/src/logger-manager.js +0 -17
  47. package/dist/src/logger.d.ts +0 -34
  48. package/dist/src/logger.d.ts.map +0 -1
  49. package/dist/src/logger.js +0 -279
  50. package/dist/src/runner.d.ts +0 -21
  51. package/dist/src/runner.d.ts.map +0 -1
  52. package/dist/src/runner.js +0 -414
  53. package/dist/src/start-manager.d.ts +0 -49
  54. package/dist/src/start-manager.d.ts.map +0 -1
  55. package/dist/src/start-manager.js +0 -484
  56. package/dist/src/types.d.ts +0 -41
  57. package/dist/src/types.d.ts.map +0 -1
  58. package/dist/src/types.js +0 -2
  59. package/dist/src/utils.d.ts +0 -2
  60. package/dist/src/utils.d.ts.map +0 -1
  61. package/dist/src/utils.js +0 -9
@@ -1,162 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.addStartCommands = addStartCommands;
7
- const start_manager_js_1 = require("../start-manager.js");
8
- const logger_manager_js_1 = require("../logger-manager.js");
9
- const chalk_1 = __importDefault(require("chalk"));
10
- const figures_1 = __importDefault(require("figures"));
11
- const path_1 = __importDefault(require("path"));
12
- const fs_1 = __importDefault(require("fs"));
13
- function addStartCommands(program) {
14
- let startManager = null;
15
- // Production start command
16
- program
17
- .command('start [file]')
18
- .description('Start production application')
19
- .option('-d, --dir <directory>', 'Working directory', process.cwd())
20
- .option('-e, --env <file>', 'Environment file to load', '.env')
21
- .option('-p, --port <port>', 'Port number', parseInt)
22
- .option('-w, --workers <count>', 'Number of worker processes', parseInt, 1)
23
- .option('-v, --verbose', 'Verbose output')
24
- .option('--watch', 'Watch for changes and restart (development mode)')
25
- .option('--no-health', 'Disable health check endpoint')
26
- .option('--health-port <port>', 'Health check port', parseInt, 3001)
27
- .option('--max-memory <limit>', 'Maximum memory before restart (e.g., 1G)')
28
- .option('--graceful-timeout <ms>', 'Graceful shutdown timeout (ms)', parseInt, 30000)
29
- .option('--inspect', 'Enable Node.js inspector')
30
- .option('--inspect-brk', 'Enable Node.js inspector with break')
31
- .option('--node-args <args>', 'Additional Node.js arguments')
32
- .action(async (file, options) => {
33
- try {
34
- const targetFile = file || 'dist/server.js';
35
- let resolvedFile = path_1.default.resolve(options.dir, targetFile);
36
- // Auto-detect main file if not found
37
- if (!fs_1.default.existsSync(resolvedFile)) {
38
- const packageJsonPath = path_1.default.join(options.dir, 'package.json');
39
- if (fs_1.default.existsSync(packageJsonPath)) {
40
- try {
41
- const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
42
- const mainFile = packageJson.main || 'index.js';
43
- const alternativeFile = path_1.default.resolve(options.dir, mainFile);
44
- if (fs_1.default.existsSync(alternativeFile)) {
45
- resolvedFile = alternativeFile;
46
- if (options.verbose) {
47
- logger_manager_js_1.loggerManager.printLine(`Using main file: ${mainFile}`, 'info');
48
- }
49
- }
50
- else {
51
- // Try common locations
52
- const commonLocations = [
53
- 'dist/server.js',
54
- 'dist/app.js',
55
- 'dist/index.js',
56
- 'build/server.js',
57
- 'build/app.js',
58
- 'build/index.js',
59
- 'server.js',
60
- 'app.js',
61
- 'index.js',
62
- ];
63
- let found = false;
64
- for (const location of commonLocations) {
65
- const testPath = path_1.default.resolve(options.dir, location);
66
- if (fs_1.default.existsSync(testPath)) {
67
- resolvedFile = testPath;
68
- found = true;
69
- if (options.verbose) {
70
- logger_manager_js_1.loggerManager.printLine(`Found application file: ${location}`, 'info');
71
- }
72
- break;
73
- }
74
- }
75
- if (!found) {
76
- throw new Error(`Application file not found. Tried: ${targetFile}, ${mainFile}, and common locations.`);
77
- }
78
- }
79
- }
80
- catch (parseError) {
81
- throw new Error(`Failed to parse package.json: ${parseError.message}`);
82
- }
83
- }
84
- else {
85
- throw new Error(`Application file not found: ${resolvedFile}`);
86
- }
87
- }
88
- // Environment detection
89
- const isDevelopment = options.watch || process.env.NODE_ENV === 'development';
90
- const isProduction = !isDevelopment;
91
- const healthCheck = options.health !== false;
92
- const defaultPort = parseInt(process.env.PORT || '8000');
93
- const port = options.port || defaultPort;
94
- // Set NODE_ENV if not already set
95
- if (!process.env.NODE_ENV) {
96
- process.env.NODE_ENV = isProduction ? 'production' : 'development';
97
- }
98
- // Startup logging
99
- const mode = isDevelopment ? 'development' : 'production';
100
- const workerText = options.workers === 1 ? 'worker' : 'workers';
101
- const clusterInfo = `(${options.workers} ${workerText})`;
102
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.play)} Starting ${mode} server ${clusterInfo}`, 'info');
103
- if (options.verbose) {
104
- logger_manager_js_1.loggerManager.printLine(`File: ${path_1.default.relative(process.cwd(), resolvedFile)}`);
105
- logger_manager_js_1.loggerManager.printLine(`Working Directory: ${options.dir}`);
106
- logger_manager_js_1.loggerManager.printLine(`Environment: ${process.env.NODE_ENV}`);
107
- logger_manager_js_1.loggerManager.printLine(`Port: ${port}`);
108
- logger_manager_js_1.loggerManager.printLine(`Workers: ${options.workers}`);
109
- if (healthCheck) {
110
- logger_manager_js_1.loggerManager.printLine(`Health Check: http://localhost:${options.healthPort}/health`);
111
- }
112
- }
113
- startManager = new start_manager_js_1.StartManager({
114
- file: resolvedFile,
115
- workingDir: options.dir,
116
- envFile: options.env,
117
- port: options.port,
118
- workers: options.workers,
119
- memoryLimit: options.maxMemory,
120
- logLevel: options.verbose ? 'verbose' : 'info',
121
- color: true, // Assuming color is always enabled
122
- verbose: options.verbose,
123
- watch: options.watch,
124
- maxCrashes: 5, // Default max crashes
125
- restartDelay: 2000, // Default restart delay
126
- healthCheck,
127
- healthPort: options.healthPort,
128
- gracefulTimeout: options.gracefulTimeout,
129
- inspect: options.inspect,
130
- inspectBrk: options.inspectBrk,
131
- nodeArgs: options.nodeArgs,
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);
147
- await startManager.start();
148
- }
149
- catch (error) {
150
- if (error instanceof Error) {
151
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} ${error.message}`, 'error');
152
- }
153
- else {
154
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Startup failed`, 'error');
155
- }
156
- process.exit(1);
157
- }
158
- });
159
- // Cleanup function is no longer needed here as it's handled within the command
160
- const cleanupStart = async () => { };
161
- return { cleanupStart };
162
- }
@@ -1,51 +0,0 @@
1
- export interface DevOptions {
2
- file: string;
3
- watch: string[];
4
- ignore: string[];
5
- extensions: string[];
6
- delay: number;
7
- color: boolean;
8
- quiet: boolean;
9
- verbose: boolean;
10
- clearConsole: boolean;
11
- inspect: boolean;
12
- inspectBrk: boolean;
13
- envFile: string;
14
- execCommand?: string;
15
- tsConfig?: string;
16
- sourceMaps: boolean;
17
- transpileOnly: boolean;
18
- nodeArgs: string[];
19
- }
20
- export declare class DevManager {
21
- private options;
22
- private process;
23
- private watcher;
24
- private isRestarting;
25
- private restartCount;
26
- private startTime;
27
- private debouncedRestart;
28
- private moduleCache;
29
- private tsCompilerOptions;
30
- private tempDir;
31
- private currentTempFile;
32
- private isShuttingDown;
33
- constructor(options: DevOptions);
34
- private setupTempDir;
35
- private loadTsConfig;
36
- private loadEnvFile;
37
- private createHash;
38
- private extractDependencies;
39
- private compileModule;
40
- private invalidateModuleCache;
41
- private createExecutableFile;
42
- private getExecuteCommand;
43
- private clearConsole;
44
- private startProcess;
45
- private stopProcess;
46
- private restart;
47
- private setupWatcher;
48
- start(): Promise<void>;
49
- stop(): Promise<void>;
50
- }
51
- //# sourceMappingURL=dev-manager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev-manager.d.ts","sourceRoot":"","sources":["../../src/dev-manager.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAUD,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,cAAc,CAAS;gBAEnB,OAAO,EAAE,UAAU;IAW/B,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,YAAY;IA2CpB,OAAO,CAAC,WAAW;IAwCnB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,mBAAmB;IA0C3B,OAAO,CAAC,aAAa;IAoDrB,OAAO,CAAC,qBAAqB;IA0B7B,OAAO,CAAC,oBAAoB;YAqCd,iBAAiB;IAoB/B,OAAO,CAAC,YAAY;YAMN,YAAY;YA2DZ,WAAW;YA6BX,OAAO;IAqBrB,OAAO,CAAC,YAAY;IAsEP,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgCtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CA6BnC"}
@@ -1,471 +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 () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.DevManager = void 0;
40
- // src/dev-manager.ts - Ultra-fast TypeScript development server like tsx
41
- const child_process_1 = require("child_process");
42
- const chokidar_1 = require("chokidar");
43
- const logger_manager_js_1 = require("./logger-manager.js");
44
- const chalk_1 = __importDefault(require("chalk"));
45
- const figures_1 = __importDefault(require("figures"));
46
- const path_1 = __importDefault(require("path"));
47
- const fs_1 = __importDefault(require("fs"));
48
- const lodash_1 = require("lodash");
49
- const ts = __importStar(require("typescript"));
50
- const crypto_1 = __importDefault(require("crypto"));
51
- class DevManager {
52
- options;
53
- process = null;
54
- watcher = null;
55
- isRestarting = false;
56
- restartCount = 0;
57
- startTime = null;
58
- debouncedRestart;
59
- moduleCache = new Map();
60
- tsCompilerOptions;
61
- tempDir;
62
- currentTempFile = null;
63
- isShuttingDown = false;
64
- constructor(options) {
65
- this.options = options;
66
- this.tempDir = path_1.default.join(process.cwd(), '.neex-temp');
67
- this.debouncedRestart = (0, lodash_1.debounce)(this.restart.bind(this), Math.max(options.delay, 100));
68
- this.tsCompilerOptions = this.loadTsConfig();
69
- this.setupTempDir();
70
- }
71
- setupTempDir() {
72
- if (fs_1.default.existsSync(this.tempDir)) {
73
- try {
74
- fs_1.default.rmSync(this.tempDir, { recursive: true, force: true });
75
- }
76
- catch (error) {
77
- // Ignore cleanup errors
78
- }
79
- }
80
- fs_1.default.mkdirSync(this.tempDir, { recursive: true });
81
- }
82
- loadTsConfig() {
83
- const configPath = this.options.tsConfig || 'tsconfig.json';
84
- const defaultOptions = {
85
- target: ts.ScriptTarget.ES2022,
86
- module: ts.ModuleKind.CommonJS,
87
- moduleResolution: ts.ModuleResolutionKind.NodeJs,
88
- allowJs: true,
89
- strict: false,
90
- esModuleInterop: true,
91
- skipLibCheck: true,
92
- forceConsistentCasingInFileNames: true,
93
- resolveJsonModule: true,
94
- declaration: false,
95
- sourceMap: this.options.sourceMaps,
96
- inlineSourceMap: false,
97
- inlineSources: false,
98
- removeComments: false,
99
- preserveConstEnums: false,
100
- isolatedModules: true, // For faster compilation
101
- };
102
- if (fs_1.default.existsSync(configPath)) {
103
- try {
104
- const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
105
- if (!configFile.error) {
106
- const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path_1.default.dirname(configPath));
107
- if (parsedConfig.errors.length === 0) {
108
- return { ...defaultOptions, ...parsedConfig.options };
109
- }
110
- }
111
- }
112
- catch (error) {
113
- // Fall back to defaults
114
- }
115
- }
116
- return defaultOptions;
117
- }
118
- loadEnvFile() {
119
- let count = 0;
120
- const envFile = this.options.envFile;
121
- if (envFile && fs_1.default.existsSync(envFile)) {
122
- try {
123
- const envContent = fs_1.default.readFileSync(envFile, 'utf8');
124
- const lines = envContent.split('\n');
125
- for (const line of lines) {
126
- const trimmed = line.trim();
127
- if (trimmed && !trimmed.startsWith('#')) {
128
- const [key, ...values] = trimmed.split('=');
129
- if (key && values.length > 0) {
130
- process.env[key.trim()] = values
131
- .join('=')
132
- .trim()
133
- .replace(/^["']|["']$/g, '');
134
- count++;
135
- }
136
- }
137
- }
138
- if (!this.options.quiet) {
139
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.play)} Loaded ${count} env variables from ${envFile}`, 'info');
140
- }
141
- }
142
- catch (error) {
143
- if (this.options.verbose) {
144
- logger_manager_js_1.loggerManager.printLine(`Failed to load ${envFile}: ${error.message}`, 'warn');
145
- }
146
- }
147
- }
148
- }
149
- createHash(content) {
150
- return crypto_1.default.createHash('md5').update(content).digest('hex');
151
- }
152
- extractDependencies(sourceCode, filePath) {
153
- const dependencies = [];
154
- const importRegex = /(?:import|require)\s*(?:\([^)]*\)|[^;]+?from\s+)?['"`]([^'"`]+)['"`]/g;
155
- let match;
156
- while ((match = importRegex.exec(sourceCode)) !== null) {
157
- const importPath = match[1];
158
- if (importPath.startsWith('.')) {
159
- let resolvedPath = path_1.default.resolve(path_1.default.dirname(filePath), importPath);
160
- // Try to resolve with extensions
161
- if (!fs_1.default.existsSync(resolvedPath)) {
162
- for (const ext of ['.ts', '.tsx', '.js', '.jsx']) {
163
- const withExt = resolvedPath + ext;
164
- if (fs_1.default.existsSync(withExt)) {
165
- resolvedPath = withExt;
166
- break;
167
- }
168
- }
169
- }
170
- // Try index files
171
- if (!fs_1.default.existsSync(resolvedPath)) {
172
- for (const ext of ['.ts', '.tsx', '.js', '.jsx']) {
173
- const indexPath = path_1.default.join(resolvedPath, 'index' + ext);
174
- if (fs_1.default.existsSync(indexPath)) {
175
- resolvedPath = indexPath;
176
- break;
177
- }
178
- }
179
- }
180
- if (fs_1.default.existsSync(resolvedPath)) {
181
- dependencies.push(resolvedPath);
182
- }
183
- }
184
- }
185
- return dependencies;
186
- }
187
- compileModule(filePath, forceRecompile = false) {
188
- const absolutePath = path_1.default.resolve(filePath);
189
- try {
190
- const sourceCode = fs_1.default.readFileSync(absolutePath, 'utf8');
191
- const hash = this.createHash(sourceCode);
192
- const cached = this.moduleCache.get(absolutePath);
193
- // Check if we can use cached version
194
- if (!forceRecompile && cached && cached.hash === hash) {
195
- return cached;
196
- }
197
- const dependencies = this.extractDependencies(sourceCode, absolutePath);
198
- // Fast transpile without type checking for development
199
- const result = ts.transpileModule(sourceCode, {
200
- compilerOptions: this.tsCompilerOptions,
201
- fileName: absolutePath,
202
- reportDiagnostics: false, // Skip diagnostics for speed
203
- });
204
- const moduleInfo = {
205
- code: result.outputText,
206
- map: result.sourceMapText,
207
- hash,
208
- timestamp: Date.now(),
209
- dependencies,
210
- };
211
- this.moduleCache.set(absolutePath, moduleInfo);
212
- if (this.options.verbose) {
213
- logger_manager_js_1.loggerManager.printLine(`Compiled ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
214
- }
215
- return moduleInfo;
216
- }
217
- catch (error) {
218
- logger_manager_js_1.loggerManager.printLine(`Compilation error: ${error.message}`, 'error');
219
- throw error;
220
- }
221
- }
222
- invalidateModuleCache(filePath) {
223
- const absolutePath = path_1.default.resolve(filePath);
224
- // Remove the file itself
225
- this.moduleCache.delete(absolutePath);
226
- // Remove any modules that depend on this file
227
- const toRemove = [];
228
- for (const [cachedPath, info] of this.moduleCache.entries()) {
229
- if (info.dependencies.includes(absolutePath)) {
230
- toRemove.push(cachedPath);
231
- }
232
- }
233
- for (const pathToRemove of toRemove) {
234
- this.moduleCache.delete(pathToRemove);
235
- }
236
- if (this.options.verbose && toRemove.length > 0) {
237
- logger_manager_js_1.loggerManager.printLine(`Invalidated ${toRemove.length + 1} modules`, 'info');
238
- }
239
- }
240
- createExecutableFile() {
241
- // Always force recompile the main file
242
- const mainModule = this.compileModule(this.options.file, true);
243
- // Create a unique temp file
244
- const timestamp = Date.now();
245
- const random = Math.random().toString(36).substr(2, 9);
246
- const tempFile = path_1.default.join(this.tempDir, `main-${timestamp}-${random}.js`);
247
- let code = mainModule.code;
248
- // Add source map support
249
- if (mainModule.map && this.options.sourceMaps) {
250
- const mapFile = tempFile + '.map';
251
- fs_1.default.writeFileSync(mapFile, mainModule.map);
252
- code += `\n//# sourceMappingURL=${path_1.default.basename(mapFile)}`;
253
- }
254
- fs_1.default.writeFileSync(tempFile, code);
255
- // Clean up old temp file
256
- if (this.currentTempFile && fs_1.default.existsSync(this.currentTempFile)) {
257
- try {
258
- fs_1.default.unlinkSync(this.currentTempFile);
259
- const mapFile = this.currentTempFile + '.map';
260
- if (fs_1.default.existsSync(mapFile)) {
261
- fs_1.default.unlinkSync(mapFile);
262
- }
263
- }
264
- catch (error) {
265
- // Ignore cleanup errors
266
- }
267
- }
268
- this.currentTempFile = tempFile;
269
- return tempFile;
270
- }
271
- async getExecuteCommand() {
272
- if (this.options.execCommand) {
273
- const parts = this.options.execCommand.split(' ');
274
- return { command: parts[0], args: parts.slice(1) };
275
- }
276
- const executableFile = this.createExecutableFile();
277
- const args = [...this.options.nodeArgs, executableFile];
278
- // Add Node.js flags
279
- if (this.options.inspect)
280
- args.unshift('--inspect');
281
- if (this.options.inspectBrk)
282
- args.unshift('--inspect-brk');
283
- if (this.options.sourceMaps)
284
- args.unshift('--enable-source-maps');
285
- return { command: 'node', args };
286
- }
287
- clearConsole() {
288
- if (this.options.clearConsole && process.stdout.isTTY) {
289
- process.stdout.write('\x1Bc'); // Clear screen and scrollback
290
- }
291
- }
292
- async startProcess() {
293
- if (this.process)
294
- return;
295
- this.loadEnvFile();
296
- try {
297
- const { command, args } = await this.getExecuteCommand();
298
- this.process = (0, child_process_1.spawn)(command, args, {
299
- stdio: ['ignore', 'pipe', 'pipe'],
300
- env: {
301
- ...process.env,
302
- NODE_ENV: process.env.NODE_ENV || 'development',
303
- FORCE_COLOR: this.options.color ? '1' : '0',
304
- NODE_OPTIONS: '--max-old-space-size=4096', // Prevent memory issues
305
- },
306
- detached: false, // Keep attached for better cleanup
307
- });
308
- this.startTime = new Date();
309
- this.restartCount++;
310
- // Handle stdout/stderr
311
- this.process.stdout?.on('data', data => {
312
- process.stdout.write(data);
313
- });
314
- this.process.stderr?.on('data', data => {
315
- process.stderr.write(data);
316
- });
317
- this.process.on('error', error => {
318
- logger_manager_js_1.loggerManager.printLine(`Process error: ${error.message}`, 'error');
319
- });
320
- this.process.on('exit', (code, signal) => {
321
- if (this.process) {
322
- this.process = null;
323
- if (!this.isRestarting && code !== 0) {
324
- const duration = this.startTime
325
- ? Date.now() - this.startTime.getTime()
326
- : 0;
327
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red('✖')} Process exited with code ${code} (${duration}ms)`, 'error');
328
- }
329
- }
330
- });
331
- }
332
- catch (error) {
333
- logger_manager_js_1.loggerManager.printLine(`Failed to start: ${error.message}`, 'error');
334
- throw error;
335
- }
336
- }
337
- async stopProcess() {
338
- if (!this.process)
339
- return;
340
- return new Promise(resolve => {
341
- const proc = this.process;
342
- this.process = null;
343
- const cleanup = () => {
344
- resolve();
345
- };
346
- proc.on('exit', cleanup);
347
- proc.on('error', cleanup);
348
- try {
349
- proc.kill('SIGTERM');
350
- // Force kill after timeout
351
- setTimeout(() => {
352
- if (!proc.killed) {
353
- proc.kill('SIGKILL');
354
- }
355
- }, 1000);
356
- }
357
- catch (error) {
358
- cleanup();
359
- }
360
- });
361
- }
362
- async restart() {
363
- if (this.isRestarting)
364
- return;
365
- this.isRestarting = true;
366
- // Clear console immediately for better UX
367
- this.clearConsole();
368
- if (!this.options.quiet) {
369
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow('⟳')} Restarting...`, 'info');
370
- }
371
- // Stop current process
372
- await this.stopProcess();
373
- // Start new process
374
- await this.startProcess();
375
- this.isRestarting = false;
376
- }
377
- setupWatcher() {
378
- const watchPatterns = this.options.watch;
379
- // Optimized ignore patterns
380
- const ignored = [
381
- 'node_modules/**',
382
- '.git/**',
383
- 'dist/**',
384
- 'build/**',
385
- '.neex-temp/**',
386
- '**/*.log',
387
- '**/*.d.ts',
388
- '**/*.map',
389
- '**/*.tsbuildinfo',
390
- ...this.options.ignore,
391
- ];
392
- this.watcher = (0, chokidar_1.watch)(watchPatterns, {
393
- ignored,
394
- ignoreInitial: true,
395
- followSymlinks: false,
396
- usePolling: false,
397
- atomic: 50, // Very fast detection
398
- awaitWriteFinish: {
399
- stabilityThreshold: 100,
400
- pollInterval: 50,
401
- },
402
- });
403
- this.watcher.on('change', (filePath) => {
404
- this.invalidateModuleCache(filePath);
405
- if (this.options.verbose) {
406
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue('●')} ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
407
- }
408
- this.debouncedRestart();
409
- });
410
- this.watcher.on('add', (filePath) => {
411
- if (this.options.verbose) {
412
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green('+')} ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
413
- }
414
- this.debouncedRestart();
415
- });
416
- this.watcher.on('unlink', (filePath) => {
417
- this.invalidateModuleCache(filePath);
418
- if (this.options.verbose) {
419
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red('-')} ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
420
- }
421
- this.debouncedRestart();
422
- });
423
- this.watcher.on('error', (error) => {
424
- logger_manager_js_1.loggerManager.printLine(`Watcher error: ${error.message}`, 'error');
425
- });
426
- }
427
- async start() {
428
- if (!fs_1.default.existsSync(this.options.file)) {
429
- throw new Error(`Target file not found: ${this.options.file}`);
430
- }
431
- const ext = path_1.default.extname(this.options.file);
432
- if (!['.ts', '.tsx', '.js', '.jsx'].includes(ext)) {
433
- throw new Error(`Unsupported file extension: ${ext}`);
434
- }
435
- // Clear any existing cache
436
- this.moduleCache.clear();
437
- this.setupTempDir();
438
- if (!this.options.quiet) {
439
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.play)} Starting TypeScript development server...`, 'info');
440
- }
441
- this.setupWatcher();
442
- await this.startProcess();
443
- if (!this.options.quiet) {
444
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green('✓')} Watching for changes...`, 'info');
445
- }
446
- }
447
- async stop() {
448
- if (this.isShuttingDown)
449
- return;
450
- this.isShuttingDown = true;
451
- if (!this.options.quiet) {
452
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow('⏹')} Stopping dev server...`, 'info');
453
- }
454
- if (this.watcher) {
455
- await this.watcher.close();
456
- this.watcher = null;
457
- }
458
- await this.stopProcess();
459
- // Cleanup temp files
460
- if (fs_1.default.existsSync(this.tempDir)) {
461
- try {
462
- fs_1.default.rmSync(this.tempDir, { recursive: true, force: true });
463
- }
464
- catch (error) {
465
- // Ignore cleanup errors
466
- }
467
- }
468
- this.moduleCache.clear();
469
- }
470
- }
471
- exports.DevManager = DevManager;