neex 0.7.44 → 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.
- package/README.md +50 -326
- package/bin/neex +31 -0
- package/install.js +94 -0
- package/package.json +30 -63
- package/dist/bin/neex.d.ts +0 -26
- package/dist/bin/neex.d.ts.map +0 -1
- package/dist/bin/neex.js +0 -8
- package/dist/src/build-manager.d.ts +0 -41
- package/dist/src/build-manager.d.ts.map +0 -1
- package/dist/src/build-manager.js +0 -369
- package/dist/src/cli.d.ts +0 -2
- package/dist/src/cli.d.ts.map +0 -1
- package/dist/src/cli.js +0 -67
- package/dist/src/commands/add-commands.d.ts +0 -4
- package/dist/src/commands/add-commands.d.ts.map +0 -1
- package/dist/src/commands/add-commands.js +0 -83
- package/dist/src/commands/build-commands.d.ts +0 -5
- package/dist/src/commands/build-commands.d.ts.map +0 -1
- package/dist/src/commands/build-commands.js +0 -123
- package/dist/src/commands/dev-commands.d.ts +0 -5
- package/dist/src/commands/dev-commands.d.ts.map +0 -1
- package/dist/src/commands/dev-commands.js +0 -198
- package/dist/src/commands/index.d.ts +0 -8
- package/dist/src/commands/index.d.ts.map +0 -1
- package/dist/src/commands/index.js +0 -27
- package/dist/src/commands/init-commands.d.ts +0 -2
- package/dist/src/commands/init-commands.d.ts.map +0 -1
- package/dist/src/commands/init-commands.js +0 -20
- package/dist/src/commands/run-commands.d.ts +0 -3
- package/dist/src/commands/run-commands.d.ts.map +0 -1
- package/dist/src/commands/run-commands.js +0 -93
- package/dist/src/commands/server-commands.d.ts +0 -3
- package/dist/src/commands/server-commands.d.ts.map +0 -1
- package/dist/src/commands/server-commands.js +0 -51
- package/dist/src/commands/start-commands.d.ts +0 -5
- package/dist/src/commands/start-commands.d.ts.map +0 -1
- package/dist/src/commands/start-commands.js +0 -162
- package/dist/src/dev-manager.d.ts +0 -51
- package/dist/src/dev-manager.d.ts.map +0 -1
- package/dist/src/dev-manager.js +0 -471
- package/dist/src/index.d.ts +0 -41
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -70
- package/dist/src/logger-manager.d.ts +0 -4
- package/dist/src/logger-manager.d.ts.map +0 -1
- package/dist/src/logger-manager.js +0 -17
- package/dist/src/logger.d.ts +0 -34
- package/dist/src/logger.d.ts.map +0 -1
- package/dist/src/logger.js +0 -279
- package/dist/src/runner.d.ts +0 -21
- package/dist/src/runner.d.ts.map +0 -1
- package/dist/src/runner.js +0 -414
- package/dist/src/start-manager.d.ts +0 -49
- package/dist/src/start-manager.d.ts.map +0 -1
- package/dist/src/start-manager.js +0 -484
- package/dist/src/types.d.ts +0 -41
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js +0 -2
- package/dist/src/utils.d.ts +0 -2
- package/dist/src/utils.d.ts.map +0 -1
- 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"}
|
package/dist/src/dev-manager.js
DELETED
|
@@ -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;
|