neex 0.2.5 → 0.2.6
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 +72 -51
- package/bun.lock +54 -6
- package/dist/src/cli.js +366 -28
- package/dist/src/process-manager.js +208 -0
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
<a href="https://github.com/Neexjs">
|
|
3
|
-
<picture>
|
|
4
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://neex.storage.c2.liara.space/Neex.png">
|
|
5
|
-
<img alt="Neex logo" src="https://neex.storage.c2.liara.space/Neex.png" height="150" style="border-radius: 12px;">
|
|
6
|
-
</picture>
|
|
7
|
-
</a>
|
|
8
|
-
|
|
9
|
-
# Neex v0.2.5
|
|
1
|
+
# Neex v0.2.6
|
|
10
2
|
|
|
11
3
|
### 🚀 Neex: The Modern Build System for Polyrepo-in-Monorepo Architecture
|
|
12
4
|
|
|
@@ -14,7 +6,6 @@
|
|
|
14
6
|
[](https://www.npmjs.com/package/neex)
|
|
15
7
|
[](https://github.com/neexjs/blob/main/LICENSE)
|
|
16
8
|
[](https://github.com/Neexjs)
|
|
17
|
-
</div>
|
|
18
9
|
|
|
19
10
|
## 🎯 Overview
|
|
20
11
|
|
|
@@ -25,7 +16,7 @@ Neex is a modern build system designed to bridge the gap between polyrepo and mo
|
|
|
25
16
|
## ✨ Key Features
|
|
26
17
|
|
|
27
18
|
- 🎨 **Colored Output** - Distinguish commands with unique colors
|
|
28
|
-
- ⚡ **Dual Execution Modes** - Run commands in parallel (`p
|
|
19
|
+
- ⚡ **Dual Execution Modes** - Run commands in parallel (`p`) or sequence (`s`)
|
|
29
20
|
- ⏱️ **Smart Timing** - Track execution time for each command
|
|
30
21
|
- 🛑 **Error Control** - Stop on first error (perfect for CI/CD)
|
|
31
22
|
- 🔢 **Parallel Control** - Limit concurrent processes with `--max-parallel`
|
|
@@ -49,22 +40,45 @@ bun add -D neex # bun
|
|
|
49
40
|
|
|
50
41
|
## 🖥️ Usage
|
|
51
42
|
|
|
52
|
-
### Commands
|
|
43
|
+
### Process Management Commands
|
|
53
44
|
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
```bash
|
|
46
|
+
# Start a process
|
|
47
|
+
neex startx app.js -n "my-app" -w
|
|
48
|
+
|
|
49
|
+
# startx options
|
|
50
|
+
-n, --name <name> Process name
|
|
51
|
+
-w, --watch Watch for file changes
|
|
52
|
+
-r, --max-restarts <number> Maximum restart attempts
|
|
53
|
+
-d, --restart-delay <ms> Delay between restarts
|
|
54
|
+
|
|
55
|
+
# Stop a process
|
|
56
|
+
neex stopx <process-id>
|
|
57
|
+
|
|
58
|
+
# List processes
|
|
59
|
+
neex list
|
|
60
|
+
neex list -a # Show all processes
|
|
61
|
+
neex list -j # JSON output
|
|
62
|
+
|
|
63
|
+
# Monitor process
|
|
64
|
+
neex monit <process-id>
|
|
65
|
+
neex monit <process-id> -i 1000 # Set update interval
|
|
66
|
+
|
|
67
|
+
# View logs
|
|
68
|
+
neex log <process-id>
|
|
69
|
+
neex log <process-id> -f # Follow logs
|
|
70
|
+
neex log <process-id> -e # Show only errors
|
|
71
|
+
neex log <process-id> -w # Show only warnings
|
|
72
|
+
```
|
|
56
73
|
|
|
57
|
-
###
|
|
74
|
+
### Script Execution Commands
|
|
58
75
|
|
|
59
76
|
```bash
|
|
60
|
-
# Parallel execution (default)
|
|
61
|
-
neex p "echo Task 1" "echo Task 2" "echo Task 3"
|
|
62
|
-
|
|
63
77
|
# Sequential execution
|
|
64
|
-
neex s "
|
|
78
|
+
neex s "npm install" "npm run build"
|
|
65
79
|
|
|
66
|
-
# Parallel
|
|
67
|
-
neex p
|
|
80
|
+
# Parallel execution
|
|
81
|
+
neex p "npm run dev" "npm run watch"
|
|
68
82
|
```
|
|
69
83
|
|
|
70
84
|
### 🛠️ Options
|
|
@@ -79,14 +93,6 @@ neex p -q "echo Step 1" "echo Step 2" "echo Step 3"
|
|
|
79
93
|
| `--max-parallel` | `-m` | Max parallel tasks | CPU count |
|
|
80
94
|
| `--sequential` | `-q` | Force sequential | `false` |
|
|
81
95
|
|
|
82
|
-
|
|
83
|
-
### Advanced Example
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
# Run tests & build with max 2 parallel tasks, stop on error
|
|
87
|
-
neex p -s -m 2 -t "npm test" "npm run build" "npm run lint"
|
|
88
|
-
```
|
|
89
|
-
|
|
90
96
|
## 📦 Node.js API
|
|
91
97
|
|
|
92
98
|
```javascript
|
|
@@ -115,20 +121,6 @@ async function main() {
|
|
|
115
121
|
}
|
|
116
122
|
```
|
|
117
123
|
|
|
118
|
-
### API Options
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
interface RunOptions {
|
|
122
|
-
parallel?: boolean; // Run in parallel (default: true)
|
|
123
|
-
maxParallel?: number; // Max parallel processes (default: CPU count)
|
|
124
|
-
color?: boolean; // Enable colors (default: true)
|
|
125
|
-
prefix?: boolean; // Show command prefix (default: true)
|
|
126
|
-
showTiming?: boolean; // Show timing info (default: true)
|
|
127
|
-
printOutput?: boolean; // Show command output (default: true)
|
|
128
|
-
stopOnError?: boolean; // Stop on failure (default: false)
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
124
|
## 🔄 CI/CD Integration
|
|
133
125
|
|
|
134
126
|
```yaml
|
|
@@ -143,17 +135,46 @@ steps:
|
|
|
143
135
|
|
|
144
136
|
## 💡 Real-world Examples
|
|
145
137
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
138
|
+
### Multi-part Project Execution
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"scripts": {
|
|
143
|
+
"dev": "neex p dev:client dev:server",
|
|
144
|
+
"dev:client": "cd apps/client && npm run dev",
|
|
145
|
+
"dev:server": "cd apps/server && npm run dev",
|
|
146
|
+
"build": "neex s build:client build:server",
|
|
147
|
+
"build:client": "cd apps/client && npm run build",
|
|
148
|
+
"build:server": "cd apps/server && npm run build",
|
|
149
|
+
"start": "neex p start:client start:server",
|
|
150
|
+
"start:client": "cd apps/client && npm run start",
|
|
151
|
+
"start:server": "cd apps/server && npm run start"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
152
155
|
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
### Production Project Management
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"scripts": {
|
|
161
|
+
"startx": "neex startx:client && neex startx:server",
|
|
162
|
+
"startx:client": "neex startx apps/client/index.js -n client -w",
|
|
163
|
+
"startx:server": "neex startx apps/server/index.js -n server -w",
|
|
164
|
+
"stopx": "neex stopx:client && neex stopx:server",
|
|
165
|
+
"stopx:client": "neex stopx client",
|
|
166
|
+
"stopx:server": "neex stopx server"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
155
169
|
```
|
|
156
170
|
|
|
171
|
+
## Important Notes
|
|
172
|
+
|
|
173
|
+
- Logs are stored in the `.neex-logs` directory
|
|
174
|
+
- Configuration is stored in `.neex-config.json`
|
|
175
|
+
- Use `Ctrl+C` to stop live monitoring
|
|
176
|
+
- Use `neex stopx -f` for force stop when needed
|
|
177
|
+
|
|
157
178
|
## 🤝 Contributing
|
|
158
179
|
|
|
159
180
|
We welcome contributions! Check our [issues page](https://github.com/Neexjs).
|
package/bun.lock
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"name": "nextpressx",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"chalk": "^4.1.2",
|
|
8
|
+
"chokidar": "^3.5.3",
|
|
8
9
|
"commander": "^9.4.0",
|
|
9
10
|
"figlet": "^1.8.1",
|
|
10
11
|
"figures": "^3.2.0",
|
|
@@ -12,8 +13,11 @@
|
|
|
12
13
|
"npm-run-path": "^4.0.1",
|
|
13
14
|
"p-map": "^4.0.0",
|
|
14
15
|
"string-width": "^4.2.3",
|
|
16
|
+
"ts-node": "^10.9.1",
|
|
17
|
+
"tsconfig-paths": "^4.2.0",
|
|
15
18
|
},
|
|
16
19
|
"devDependencies": {
|
|
20
|
+
"@types/chokidar": "^2.1.7",
|
|
17
21
|
"@types/figlet": "^1.7.0",
|
|
18
22
|
"@types/jest": "^29.2.3",
|
|
19
23
|
"@types/node": "^18.11.9",
|
|
@@ -94,6 +98,8 @@
|
|
|
94
98
|
|
|
95
99
|
"@bcoe/v8-coverage": ["@bcoe/v8-coverage@0.2.3", "", {}, "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="],
|
|
96
100
|
|
|
101
|
+
"@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
|
|
102
|
+
|
|
97
103
|
"@istanbuljs/load-nyc-config": ["@istanbuljs/load-nyc-config@1.1.0", "", { "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" } }, "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ=="],
|
|
98
104
|
|
|
99
105
|
"@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="],
|
|
@@ -142,6 +148,14 @@
|
|
|
142
148
|
|
|
143
149
|
"@sinonjs/fake-timers": ["@sinonjs/fake-timers@10.3.0", "", { "dependencies": { "@sinonjs/commons": "^3.0.0" } }, "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA=="],
|
|
144
150
|
|
|
151
|
+
"@tsconfig/node10": ["@tsconfig/node10@1.0.11", "", {}, "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw=="],
|
|
152
|
+
|
|
153
|
+
"@tsconfig/node12": ["@tsconfig/node12@1.0.11", "", {}, "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="],
|
|
154
|
+
|
|
155
|
+
"@tsconfig/node14": ["@tsconfig/node14@1.0.3", "", {}, "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="],
|
|
156
|
+
|
|
157
|
+
"@tsconfig/node16": ["@tsconfig/node16@1.0.4", "", {}, "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="],
|
|
158
|
+
|
|
145
159
|
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
|
|
146
160
|
|
|
147
161
|
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
|
|
@@ -150,6 +164,8 @@
|
|
|
150
164
|
|
|
151
165
|
"@types/babel__traverse": ["@types/babel__traverse@7.20.7", "", { "dependencies": { "@babel/types": "^7.20.7" } }, "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng=="],
|
|
152
166
|
|
|
167
|
+
"@types/chokidar": ["@types/chokidar@2.1.7", "", { "dependencies": { "chokidar": "*" } }, "sha512-A7/MFHf6KF7peCzjEC1BBTF8jpmZTokb3vr/A0NxRGfwRLK3Ws+Hq6ugVn6cJIMfM6wkCak/aplWrxbTcu8oig=="],
|
|
168
|
+
|
|
153
169
|
"@types/figlet": ["@types/figlet@1.7.0", "", {}, "sha512-KwrT7p/8Eo3Op/HBSIwGXOsTZKYiM9NpWRBJ5sVjWP/SmlS+oxxRvJht/FNAtliJvja44N3ul1yATgohnVBV0Q=="],
|
|
154
170
|
|
|
155
171
|
"@types/graceful-fs": ["@types/graceful-fs@4.1.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ=="],
|
|
@@ -172,6 +188,10 @@
|
|
|
172
188
|
|
|
173
189
|
"@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="],
|
|
174
190
|
|
|
191
|
+
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
|
192
|
+
|
|
193
|
+
"acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="],
|
|
194
|
+
|
|
175
195
|
"aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="],
|
|
176
196
|
|
|
177
197
|
"ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
|
|
@@ -182,6 +202,8 @@
|
|
|
182
202
|
|
|
183
203
|
"anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
|
|
184
204
|
|
|
205
|
+
"arg": ["arg@4.1.3", "", {}, "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="],
|
|
206
|
+
|
|
185
207
|
"argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
|
186
208
|
|
|
187
209
|
"async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="],
|
|
@@ -198,6 +220,8 @@
|
|
|
198
220
|
|
|
199
221
|
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
|
200
222
|
|
|
223
|
+
"binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
|
|
224
|
+
|
|
201
225
|
"brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
|
202
226
|
|
|
203
227
|
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
|
@@ -220,6 +244,8 @@
|
|
|
220
244
|
|
|
221
245
|
"char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="],
|
|
222
246
|
|
|
247
|
+
"chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
|
|
248
|
+
|
|
223
249
|
"ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="],
|
|
224
250
|
|
|
225
251
|
"cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
|
|
@@ -244,6 +270,8 @@
|
|
|
244
270
|
|
|
245
271
|
"create-jest": ["create-jest@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-config": "^29.7.0", "jest-util": "^29.7.0", "prompts": "^2.0.1" }, "bin": "bin/create-jest.js" }, "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q=="],
|
|
246
272
|
|
|
273
|
+
"create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="],
|
|
274
|
+
|
|
247
275
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
|
248
276
|
|
|
249
277
|
"debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="],
|
|
@@ -254,6 +282,8 @@
|
|
|
254
282
|
|
|
255
283
|
"detect-newline": ["detect-newline@3.1.0", "", {}, "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA=="],
|
|
256
284
|
|
|
285
|
+
"diff": ["diff@4.0.2", "", {}, "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="],
|
|
286
|
+
|
|
257
287
|
"diff-sequences": ["diff-sequences@29.6.3", "", {}, "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q=="],
|
|
258
288
|
|
|
259
289
|
"ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": "bin/cli.js" }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="],
|
|
@@ -308,6 +338,8 @@
|
|
|
308
338
|
|
|
309
339
|
"glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
|
310
340
|
|
|
341
|
+
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
|
342
|
+
|
|
311
343
|
"globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
|
|
312
344
|
|
|
313
345
|
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
|
@@ -334,12 +366,18 @@
|
|
|
334
366
|
|
|
335
367
|
"is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
|
|
336
368
|
|
|
369
|
+
"is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="],
|
|
370
|
+
|
|
337
371
|
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
|
|
338
372
|
|
|
373
|
+
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
|
374
|
+
|
|
339
375
|
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
|
340
376
|
|
|
341
377
|
"is-generator-fn": ["is-generator-fn@2.1.0", "", {}, "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ=="],
|
|
342
378
|
|
|
379
|
+
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
|
380
|
+
|
|
343
381
|
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
|
344
382
|
|
|
345
383
|
"is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
|
|
@@ -446,6 +484,8 @@
|
|
|
446
484
|
|
|
447
485
|
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
|
448
486
|
|
|
487
|
+
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
|
488
|
+
|
|
449
489
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
450
490
|
|
|
451
491
|
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
|
@@ -496,6 +536,8 @@
|
|
|
496
536
|
|
|
497
537
|
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
|
498
538
|
|
|
539
|
+
"readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
|
|
540
|
+
|
|
499
541
|
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
|
|
500
542
|
|
|
501
543
|
"resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="],
|
|
@@ -532,7 +574,7 @@
|
|
|
532
574
|
|
|
533
575
|
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
|
534
576
|
|
|
535
|
-
"strip-bom": ["strip-bom@
|
|
577
|
+
"strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
|
|
536
578
|
|
|
537
579
|
"strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
|
|
538
580
|
|
|
@@ -554,6 +596,10 @@
|
|
|
554
596
|
|
|
555
597
|
"ts-jest": ["ts-jest@29.3.2", "", { "dependencies": { "bs-logger": "^0.2.6", "ejs": "^3.1.10", "fast-json-stable-stringify": "^2.1.0", "jest-util": "^29.0.0", "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", "semver": "^7.7.1", "type-fest": "^4.39.1", "yargs-parser": "^21.1.1" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", "@jest/transform": "^29.0.0", "@jest/types": "^29.0.0", "babel-jest": "^29.0.0", "jest": "^29.0.0", "typescript": ">=4.3 <6" }, "bin": "cli.js" }, "sha512-bJJkrWc6PjFVz5g2DGCNUo8z7oFEYaz1xP1NpeDU7KNLMWPpEyV8Chbpkn8xjzgRDpQhnGMyvyldoL7h8JXyug=="],
|
|
556
598
|
|
|
599
|
+
"ts-node": ["ts-node@10.9.2", "", { "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "optionalPeers": ["@swc/core", "@swc/wasm"], "bin": { "ts-node": "dist/bin.js", "ts-script": "dist/bin-script-deprecated.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js" } }, "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ=="],
|
|
600
|
+
|
|
601
|
+
"tsconfig-paths": ["tsconfig-paths@4.2.0", "", { "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg=="],
|
|
602
|
+
|
|
557
603
|
"type-detect": ["type-detect@4.0.8", "", {}, "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="],
|
|
558
604
|
|
|
559
605
|
"type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
|
|
@@ -564,6 +610,8 @@
|
|
|
564
610
|
|
|
565
611
|
"update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": "cli.js" }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],
|
|
566
612
|
|
|
613
|
+
"v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="],
|
|
614
|
+
|
|
567
615
|
"v8-to-istanbul": ["v8-to-istanbul@9.3.0", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^2.0.0" } }, "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA=="],
|
|
568
616
|
|
|
569
617
|
"walker": ["walker@1.0.8", "", { "dependencies": { "makeerror": "1.0.12" } }, "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ=="],
|
|
@@ -584,12 +632,16 @@
|
|
|
584
632
|
|
|
585
633
|
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
|
|
586
634
|
|
|
635
|
+
"yn": ["yn@3.1.1", "", {}, "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="],
|
|
636
|
+
|
|
587
637
|
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
|
588
638
|
|
|
589
639
|
"@babel/core/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
|
590
640
|
|
|
591
641
|
"@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
|
592
642
|
|
|
643
|
+
"@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
|
|
644
|
+
|
|
593
645
|
"@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="],
|
|
594
646
|
|
|
595
647
|
"ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
|
|
@@ -600,14 +652,10 @@
|
|
|
600
652
|
|
|
601
653
|
"gradient-string/chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="],
|
|
602
654
|
|
|
603
|
-
"
|
|
604
|
-
|
|
605
|
-
"jest-snapshot/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
|
655
|
+
"jest-runtime/strip-bom": ["strip-bom@4.0.0", "", {}, "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w=="],
|
|
606
656
|
|
|
607
657
|
"jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
|
608
658
|
|
|
609
|
-
"make-dir/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
|
610
|
-
|
|
611
659
|
"p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
|
612
660
|
|
|
613
661
|
"pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
package/dist/src/cli.js
CHANGED
|
@@ -8,6 +8,11 @@ const commander_1 = require("commander");
|
|
|
8
8
|
const index_js_1 = require("./index.js");
|
|
9
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
10
10
|
const figures_1 = __importDefault(require("figures"));
|
|
11
|
+
const chokidar_1 = require("chokidar");
|
|
12
|
+
const child_process_1 = require("child_process");
|
|
13
|
+
const path_1 = require("path");
|
|
14
|
+
const fs_1 = require("fs");
|
|
15
|
+
const process_manager_js_1 = require("./process-manager.js");
|
|
11
16
|
const { version } = require('../../package.json');
|
|
12
17
|
function cli() {
|
|
13
18
|
const program = new commander_1.Command();
|
|
@@ -16,9 +21,142 @@ function cli() {
|
|
|
16
21
|
.name('neex')
|
|
17
22
|
.description('Professional script runner with beautiful colored output')
|
|
18
23
|
.version(version);
|
|
19
|
-
//
|
|
24
|
+
// Development command for Express.js projects
|
|
20
25
|
program
|
|
21
|
-
.command('
|
|
26
|
+
.command('dev <entry>')
|
|
27
|
+
.description('Run Express.js project in development mode with TypeScript support')
|
|
28
|
+
.option('-p, --port <number>', 'Port to run the server on', '3000')
|
|
29
|
+
.option('-w, --watch <path>', 'Path to watch for changes', 'src')
|
|
30
|
+
.option('-c, --no-color', 'Disable colored output')
|
|
31
|
+
.action(async (entry, options) => {
|
|
32
|
+
try {
|
|
33
|
+
const entryPath = (0, path_1.resolve)(process.cwd(), entry);
|
|
34
|
+
if (!(0, fs_1.existsSync)(entryPath)) {
|
|
35
|
+
throw new Error(`Entry file ${entry} not found`);
|
|
36
|
+
}
|
|
37
|
+
console.log(chalk_1.default.blue(`${figures_1.default.info} Starting development server...`));
|
|
38
|
+
let server = (0, child_process_1.spawn)('ts-node', [
|
|
39
|
+
'-r', 'tsconfig-paths/register',
|
|
40
|
+
entryPath
|
|
41
|
+
], {
|
|
42
|
+
stdio: 'inherit',
|
|
43
|
+
env: {
|
|
44
|
+
...process.env,
|
|
45
|
+
PORT: options.port
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
// Setup file watching
|
|
49
|
+
const watcher = (0, chokidar_1.watch)(options.watch, {
|
|
50
|
+
ignored: /(^|[\/\\])\../,
|
|
51
|
+
persistent: true
|
|
52
|
+
});
|
|
53
|
+
watcher.on('change', (path) => {
|
|
54
|
+
console.log(chalk_1.default.yellow(`${figures_1.default.info} File ${path} changed. Restarting...`));
|
|
55
|
+
server.kill();
|
|
56
|
+
server = (0, child_process_1.spawn)('ts-node', [
|
|
57
|
+
'-r', 'tsconfig-paths/register',
|
|
58
|
+
entryPath
|
|
59
|
+
], {
|
|
60
|
+
stdio: 'inherit',
|
|
61
|
+
env: {
|
|
62
|
+
...process.env,
|
|
63
|
+
PORT: options.port
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
cleanupRunner = () => {
|
|
68
|
+
server.kill();
|
|
69
|
+
watcher.close();
|
|
70
|
+
};
|
|
71
|
+
server.on('error', (err) => {
|
|
72
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} Server error: ${err.message}`));
|
|
73
|
+
process.exit(1);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (error instanceof Error) {
|
|
78
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} Error: ${error.message}`));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown error occurred`));
|
|
82
|
+
}
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
// Build command for TypeScript compilation
|
|
87
|
+
program
|
|
88
|
+
.command('build')
|
|
89
|
+
.description('Build TypeScript project')
|
|
90
|
+
.option('-o, --outDir <dir>', 'Output directory', 'dist')
|
|
91
|
+
.action(async (options) => {
|
|
92
|
+
try {
|
|
93
|
+
console.log(chalk_1.default.blue(`${figures_1.default.info} Building project...`));
|
|
94
|
+
const build = (0, child_process_1.spawn)('tsc', [
|
|
95
|
+
'--outDir', options.outDir
|
|
96
|
+
], {
|
|
97
|
+
stdio: 'inherit'
|
|
98
|
+
});
|
|
99
|
+
build.on('close', (code) => {
|
|
100
|
+
if (code === 0) {
|
|
101
|
+
console.log(chalk_1.default.green(`${figures_1.default.tick} Build completed successfully`));
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} Build failed with code ${code}`));
|
|
105
|
+
process.exit(code !== null && code !== void 0 ? code : 1);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (error instanceof Error) {
|
|
111
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} Error: ${error.message}`));
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown error occurred`));
|
|
115
|
+
}
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
// Start command for production
|
|
120
|
+
program
|
|
121
|
+
.command('start <entry>')
|
|
122
|
+
.description('Start Express.js project in production mode')
|
|
123
|
+
.option('-p, --port <number>', 'Port to run the server on', '3000')
|
|
124
|
+
.action(async (entry, options) => {
|
|
125
|
+
try {
|
|
126
|
+
const entryPath = (0, path_1.resolve)(process.cwd(), entry);
|
|
127
|
+
if (!(0, fs_1.existsSync)(entryPath)) {
|
|
128
|
+
throw new Error(`Entry file ${entry} not found`);
|
|
129
|
+
}
|
|
130
|
+
console.log(chalk_1.default.blue(`${figures_1.default.info} Starting production server...`));
|
|
131
|
+
const server = (0, child_process_1.spawn)('node', [entryPath], {
|
|
132
|
+
stdio: 'inherit',
|
|
133
|
+
env: {
|
|
134
|
+
...process.env,
|
|
135
|
+
PORT: options.port,
|
|
136
|
+
NODE_ENV: 'production'
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
cleanupRunner = () => {
|
|
140
|
+
server.kill();
|
|
141
|
+
};
|
|
142
|
+
server.on('error', (err) => {
|
|
143
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} Server error: ${err.message}`));
|
|
144
|
+
process.exit(1);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
if (error instanceof Error) {
|
|
149
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} Error: ${error.message}`));
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown error occurred`));
|
|
153
|
+
}
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
// Main command for sequential execution (similar to )
|
|
158
|
+
program
|
|
159
|
+
.command('sequential <commands...>')
|
|
22
160
|
.alias('s')
|
|
23
161
|
.description('Run commands sequentially')
|
|
24
162
|
.option('-c, --no-color', 'Disable colored output')
|
|
@@ -52,7 +190,7 @@ function cli() {
|
|
|
52
190
|
});
|
|
53
191
|
// runx command: parallel execution by default (with alias 'p'), can run sequentially with -q
|
|
54
192
|
program
|
|
55
|
-
.command('
|
|
193
|
+
.command('parallel <commands...>', { isDefault: true })
|
|
56
194
|
.alias('p')
|
|
57
195
|
.description('Run commands in parallel (default) or sequentially with -q. Alias: p')
|
|
58
196
|
.option('-c, --no-color', 'Disable colored output')
|
|
@@ -87,39 +225,239 @@ function cli() {
|
|
|
87
225
|
process.exit(1);
|
|
88
226
|
}
|
|
89
227
|
});
|
|
90
|
-
//
|
|
228
|
+
// Process Management Commands
|
|
91
229
|
program
|
|
92
|
-
.command('
|
|
93
|
-
.
|
|
94
|
-
.
|
|
95
|
-
.option('-
|
|
96
|
-
.option('-
|
|
97
|
-
.option('-
|
|
98
|
-
.
|
|
99
|
-
.option('-x, --max-parallel <number>', 'Maximum number of parallel servers', parseInt)
|
|
100
|
-
.option('-g, --group-output', 'Group outputs by server')
|
|
101
|
-
.action(async (commands, options) => {
|
|
230
|
+
.command('startx <path>')
|
|
231
|
+
.description('Start a process with monitoring and auto-restart')
|
|
232
|
+
.option('-n, --name <name>', 'Process name')
|
|
233
|
+
.option('-w, --watch', 'Watch for file changes and auto-restart')
|
|
234
|
+
.option('-r, --max-restarts <number>', 'Maximum number of restart attempts', '5')
|
|
235
|
+
.option('-d, --restart-delay <number>', 'Delay between restarts in milliseconds', '1000')
|
|
236
|
+
.action(async (path, options) => {
|
|
102
237
|
try {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
238
|
+
const process = await process_manager_js_1.processManager.startx(path, {
|
|
239
|
+
name: options.name,
|
|
240
|
+
watch: options.watch,
|
|
241
|
+
maxRestarts: parseInt(options.maxRestarts),
|
|
242
|
+
restartDelay: parseInt(options.restartDelay)
|
|
243
|
+
});
|
|
244
|
+
console.log(chalk_1.default.green(`${figures_1.default.tick} Process started successfully`));
|
|
245
|
+
console.log(chalk_1.default.blue(`ID: ${process.id}`));
|
|
246
|
+
console.log(chalk_1.default.blue(`Name: ${process.name}`));
|
|
247
|
+
console.log(chalk_1.default.blue(`PID: ${process.pid}`));
|
|
248
|
+
console.log(chalk_1.default.blue(`Max Restarts: ${process.maxRestarts}`));
|
|
249
|
+
console.log(chalk_1.default.blue(`Restart Delay: ${process.restartDelay}ms`));
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
if (error instanceof Error) {
|
|
253
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} Error: ${error.message}`));
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown error occurred`));
|
|
257
|
+
}
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
program
|
|
262
|
+
.command('stopx <id>')
|
|
263
|
+
.description('Stop a running process')
|
|
264
|
+
.option('-f, --force', 'Force stop the process')
|
|
265
|
+
.action(async (id, options) => {
|
|
266
|
+
try {
|
|
267
|
+
await process_manager_js_1.processManager.stopx(id);
|
|
268
|
+
console.log(chalk_1.default.green(`${figures_1.default.tick} Process stopped successfully`));
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
if (error instanceof Error) {
|
|
272
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} Error: ${error.message}`));
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown error occurred`));
|
|
276
|
+
}
|
|
277
|
+
process.exit(1);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
program
|
|
281
|
+
.command('list')
|
|
282
|
+
.description('List all running processes')
|
|
283
|
+
.option('-a, --all', 'Show all processes including stopped ones')
|
|
284
|
+
.option('-j, --json', 'Output in JSON format')
|
|
285
|
+
.action((options) => {
|
|
286
|
+
const processes = process_manager_js_1.processManager.list();
|
|
287
|
+
const filteredProcesses = options.all ? processes : processes.filter(p => p.status === 'running');
|
|
288
|
+
if (filteredProcesses.length === 0) {
|
|
289
|
+
console.log(chalk_1.default.yellow(`${figures_1.default.info} No processes running`));
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (options.json) {
|
|
293
|
+
console.log(JSON.stringify(filteredProcesses, null, 2));
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
console.log(chalk_1.default.blue(`${figures_1.default.info} Running Processes:`));
|
|
297
|
+
filteredProcesses.forEach(process => {
|
|
298
|
+
const statusColor = process.status === 'running' ? 'green' :
|
|
299
|
+
process.status === 'error' ? 'red' :
|
|
300
|
+
process.status === 'restarting' ? 'yellow' : 'gray';
|
|
301
|
+
console.log(chalk_1.default.blue(`\nID: ${process.id}`));
|
|
302
|
+
console.log(`Name: ${process.name}`);
|
|
303
|
+
console.log(`Status: ${chalk_1.default[statusColor](process.status)}`);
|
|
304
|
+
console.log(`PID: ${process.pid}`);
|
|
305
|
+
console.log(`Uptime: ${Math.floor(process.uptime)}s`);
|
|
306
|
+
console.log(`Memory: ${process.memory.toFixed(2)}MB`);
|
|
307
|
+
console.log(`Restarts: ${process.restarts}/${process.maxRestarts}`);
|
|
308
|
+
if (process.lastError) {
|
|
309
|
+
console.log(`Last Error: ${chalk_1.default.red(process.lastError)}`);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
program
|
|
314
|
+
.command('monit <id>')
|
|
315
|
+
.description('Monitor a specific process')
|
|
316
|
+
.option('-i, --interval <number>', 'Update interval in milliseconds', '1000')
|
|
317
|
+
.action((id, options) => {
|
|
318
|
+
try {
|
|
319
|
+
const processInfo = process_manager_js_1.processManager.monit(id);
|
|
320
|
+
console.log(chalk_1.default.blue(`${figures_1.default.info} Process Monitor:`));
|
|
321
|
+
console.log(chalk_1.default.blue(`\nID: ${processInfo.id}`));
|
|
322
|
+
console.log(`Name: ${processInfo.name}`);
|
|
323
|
+
console.log(`Status: ${processInfo.status}`);
|
|
324
|
+
console.log(`PID: ${processInfo.pid}`);
|
|
325
|
+
console.log(`Uptime: ${Math.floor(processInfo.uptime)}s`);
|
|
326
|
+
console.log(`Memory: ${processInfo.memory.toFixed(2)}MB`);
|
|
327
|
+
console.log(`Restarts: ${processInfo.restarts}/${processInfo.maxRestarts}`);
|
|
328
|
+
if (processInfo.lastError) {
|
|
329
|
+
console.log(`Last Error: ${chalk_1.default.red(processInfo.lastError)}`);
|
|
330
|
+
}
|
|
331
|
+
console.log(chalk_1.default.blue(`\nRecent Logs:`));
|
|
332
|
+
processInfo.logs.forEach(log => {
|
|
333
|
+
if (log.includes('error') || log.includes('Error')) {
|
|
334
|
+
console.log(chalk_1.default.red(log));
|
|
335
|
+
}
|
|
336
|
+
else if (log.includes('warn') || log.includes('Warn')) {
|
|
337
|
+
console.log(chalk_1.default.yellow(log));
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
console.log(log);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
// Start real-time monitoring
|
|
344
|
+
const interval = setInterval(() => {
|
|
345
|
+
try {
|
|
346
|
+
const updatedProcess = process_manager_js_1.processManager.monit(id);
|
|
347
|
+
process.stdout.write('\x1Bc'); // Clear screen
|
|
348
|
+
console.log(chalk_1.default.blue(`${figures_1.default.info} Process Monitor (Live):`));
|
|
349
|
+
console.log(chalk_1.default.blue(`\nID: ${updatedProcess.id}`));
|
|
350
|
+
console.log(`Name: ${updatedProcess.name}`);
|
|
351
|
+
console.log(`Status: ${updatedProcess.status}`);
|
|
352
|
+
console.log(`PID: ${updatedProcess.pid}`);
|
|
353
|
+
console.log(`Uptime: ${Math.floor(updatedProcess.uptime)}s`);
|
|
354
|
+
console.log(`Memory: ${updatedProcess.memory.toFixed(2)}MB`);
|
|
355
|
+
console.log(`Restarts: ${updatedProcess.restarts}/${updatedProcess.maxRestarts}`);
|
|
356
|
+
if (updatedProcess.lastError) {
|
|
357
|
+
console.log(`Last Error: ${chalk_1.default.red(updatedProcess.lastError)}`);
|
|
358
|
+
}
|
|
359
|
+
console.log(chalk_1.default.blue(`\nRecent Logs:`));
|
|
360
|
+
updatedProcess.logs.forEach(log => {
|
|
361
|
+
if (log.includes('error') || log.includes('Error')) {
|
|
362
|
+
console.log(chalk_1.default.red(log));
|
|
363
|
+
}
|
|
364
|
+
else if (log.includes('warn') || log.includes('Warn')) {
|
|
365
|
+
console.log(chalk_1.default.yellow(log));
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
console.log(log);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
catch (error) {
|
|
373
|
+
clearInterval(interval);
|
|
374
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} Error monitoring process: ${error}`));
|
|
375
|
+
process.exit(1);
|
|
376
|
+
}
|
|
377
|
+
}, parseInt(options.interval));
|
|
378
|
+
// Handle cleanup
|
|
379
|
+
process.on('SIGINT', () => {
|
|
380
|
+
clearInterval(interval);
|
|
381
|
+
process.exit(0);
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
if (error instanceof Error) {
|
|
386
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} Error: ${error.message}`));
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown error occurred`));
|
|
390
|
+
}
|
|
391
|
+
process.exit(1);
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
program
|
|
395
|
+
.command('log <id>')
|
|
396
|
+
.description('View process logs')
|
|
397
|
+
.option('-l, --lines <number>', 'Number of lines to show', '100')
|
|
398
|
+
.option('-f, --follow', 'Follow log output')
|
|
399
|
+
.option('-e, --error', 'Show only error logs')
|
|
400
|
+
.option('-w, --warn', 'Show only warning logs')
|
|
401
|
+
.action((id, options) => {
|
|
402
|
+
try {
|
|
403
|
+
const logs = process_manager_js_1.processManager.log(id, parseInt(options.lines));
|
|
404
|
+
if (options.error) {
|
|
405
|
+
const errorLogs = logs.filter(log => log.toLowerCase().includes('error') ||
|
|
406
|
+
log.toLowerCase().includes('exception'));
|
|
407
|
+
console.log(chalk_1.default.blue(`${figures_1.default.info} Error Logs:`));
|
|
408
|
+
errorLogs.forEach(log => console.log(chalk_1.default.red(log)));
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (options.warn) {
|
|
412
|
+
const warnLogs = logs.filter(log => log.toLowerCase().includes('warn') ||
|
|
413
|
+
log.toLowerCase().includes('warning'));
|
|
414
|
+
console.log(chalk_1.default.blue(`${figures_1.default.info} Warning Logs:`));
|
|
415
|
+
warnLogs.forEach(log => console.log(chalk_1.default.yellow(log)));
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
console.log(chalk_1.default.blue(`${figures_1.default.info} Process Logs:`));
|
|
419
|
+
logs.forEach(log => {
|
|
420
|
+
if (log.includes('error') || log.includes('Error')) {
|
|
421
|
+
console.log(chalk_1.default.red(log));
|
|
422
|
+
}
|
|
423
|
+
else if (log.includes('warn') || log.includes('Warn')) {
|
|
424
|
+
console.log(chalk_1.default.yellow(log));
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
console.log(log);
|
|
428
|
+
}
|
|
115
429
|
});
|
|
430
|
+
if (options.follow) {
|
|
431
|
+
const watcher = (0, chokidar_1.watch)(process_manager_js_1.processManager.getLogPath(id), {
|
|
432
|
+
persistent: true
|
|
433
|
+
});
|
|
434
|
+
watcher.on('change', () => {
|
|
435
|
+
const newLogs = process_manager_js_1.processManager.log(id, 1);
|
|
436
|
+
if (newLogs.length > 0) {
|
|
437
|
+
const log = newLogs[0];
|
|
438
|
+
if (log.includes('error') || log.includes('Error')) {
|
|
439
|
+
console.log(chalk_1.default.red(log));
|
|
440
|
+
}
|
|
441
|
+
else if (log.includes('warn') || log.includes('Warn')) {
|
|
442
|
+
console.log(chalk_1.default.yellow(log));
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
console.log(log);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
process.on('SIGINT', () => {
|
|
450
|
+
watcher.close();
|
|
451
|
+
process.exit(0);
|
|
452
|
+
});
|
|
453
|
+
}
|
|
116
454
|
}
|
|
117
455
|
catch (error) {
|
|
118
456
|
if (error instanceof Error) {
|
|
119
|
-
console.error(chalk_1.default.red(`${figures_1.default.cross}
|
|
457
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} Error: ${error.message}`));
|
|
120
458
|
}
|
|
121
459
|
else {
|
|
122
|
-
console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown
|
|
460
|
+
console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown error occurred`));
|
|
123
461
|
}
|
|
124
462
|
process.exit(1);
|
|
125
463
|
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processManager = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const chokidar_1 = require("chokidar");
|
|
6
|
+
const fs_1 = require("fs");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
const events_1 = require("events");
|
|
9
|
+
class ProcessManager extends events_1.EventEmitter {
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.processes = new Map();
|
|
13
|
+
this.watchers = new Map();
|
|
14
|
+
this.defaultMaxRestarts = 5;
|
|
15
|
+
this.defaultRestartDelay = 1000; // 1 second
|
|
16
|
+
this.logDir = (0, path_1.resolve)(process.cwd(), '.neex-logs');
|
|
17
|
+
this.configFile = (0, path_1.resolve)(process.cwd(), '.neex-config.json');
|
|
18
|
+
this.initialize();
|
|
19
|
+
}
|
|
20
|
+
initialize() {
|
|
21
|
+
if (!(0, fs_1.existsSync)(this.logDir)) {
|
|
22
|
+
(0, fs_1.mkdirSync)(this.logDir, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
this.loadConfig();
|
|
25
|
+
}
|
|
26
|
+
loadConfig() {
|
|
27
|
+
if ((0, fs_1.existsSync)(this.configFile)) {
|
|
28
|
+
const config = JSON.parse((0, fs_1.readFileSync)(this.configFile, 'utf-8'));
|
|
29
|
+
this.processes = new Map(Object.entries(config));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
saveConfig() {
|
|
33
|
+
const config = Object.fromEntries(this.processes);
|
|
34
|
+
(0, fs_1.writeFileSync)(this.configFile, JSON.stringify(config, null, 2));
|
|
35
|
+
}
|
|
36
|
+
generateId() {
|
|
37
|
+
return Math.random().toString(36).substring(2, 15);
|
|
38
|
+
}
|
|
39
|
+
getLogPath(id) {
|
|
40
|
+
return (0, path_1.join)(this.logDir, `${id}.log`);
|
|
41
|
+
}
|
|
42
|
+
async startx(path, options = {}) {
|
|
43
|
+
const id = this.generateId();
|
|
44
|
+
const name = options.name || `process-${id}`;
|
|
45
|
+
const fullPath = (0, path_1.resolve)(process.cwd(), path);
|
|
46
|
+
if (!(0, fs_1.existsSync)(fullPath)) {
|
|
47
|
+
throw new Error(`Path ${path} does not exist`);
|
|
48
|
+
}
|
|
49
|
+
const processInfo = {
|
|
50
|
+
id,
|
|
51
|
+
name,
|
|
52
|
+
pid: 0,
|
|
53
|
+
status: 'stopped',
|
|
54
|
+
startTime: Date.now(),
|
|
55
|
+
path: fullPath,
|
|
56
|
+
command: `node ${fullPath}`,
|
|
57
|
+
logs: [],
|
|
58
|
+
memory: 0,
|
|
59
|
+
cpu: 0,
|
|
60
|
+
uptime: 0,
|
|
61
|
+
restarts: 0,
|
|
62
|
+
maxRestarts: options.maxRestarts || this.defaultMaxRestarts,
|
|
63
|
+
restartDelay: options.restartDelay || this.defaultRestartDelay,
|
|
64
|
+
watch: options.watch
|
|
65
|
+
};
|
|
66
|
+
try {
|
|
67
|
+
await this.startProcess(processInfo);
|
|
68
|
+
return processInfo;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
processInfo.status = 'error';
|
|
72
|
+
processInfo.lastError = error.message;
|
|
73
|
+
this.processes.set(id, processInfo);
|
|
74
|
+
this.saveConfig();
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async startProcess(processInfo) {
|
|
79
|
+
var _a, _b;
|
|
80
|
+
const child = (0, child_process_1.spawn)('node', [processInfo.path], {
|
|
81
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
82
|
+
env: { ...process.env, NODE_ENV: 'production' }
|
|
83
|
+
});
|
|
84
|
+
processInfo.pid = child.pid || 0;
|
|
85
|
+
processInfo.status = 'running';
|
|
86
|
+
processInfo.startTime = Date.now();
|
|
87
|
+
// Setup logging
|
|
88
|
+
const logStream = (0, fs_1.writeFileSync)(this.getLogPath(processInfo.id), '', { flag: 'a' });
|
|
89
|
+
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
|
|
90
|
+
const log = data.toString();
|
|
91
|
+
processInfo.logs.push(log);
|
|
92
|
+
(0, fs_1.writeFileSync)(this.getLogPath(processInfo.id), log, { flag: 'a' });
|
|
93
|
+
this.emit('log', { id: processInfo.id, log });
|
|
94
|
+
});
|
|
95
|
+
(_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
|
|
96
|
+
const log = data.toString();
|
|
97
|
+
processInfo.logs.push(log);
|
|
98
|
+
(0, fs_1.writeFileSync)(this.getLogPath(processInfo.id), log, { flag: 'a' });
|
|
99
|
+
this.emit('error', { id: processInfo.id, log });
|
|
100
|
+
});
|
|
101
|
+
// Setup monitoring
|
|
102
|
+
if (processInfo.watch) {
|
|
103
|
+
const watcher = (0, chokidar_1.watch)(processInfo.path, {
|
|
104
|
+
ignored: /(^|[\/\\])\../,
|
|
105
|
+
persistent: true
|
|
106
|
+
});
|
|
107
|
+
watcher.on('change', () => {
|
|
108
|
+
this.restart(processInfo.id);
|
|
109
|
+
});
|
|
110
|
+
this.watchers.set(processInfo.id, watcher);
|
|
111
|
+
}
|
|
112
|
+
// Monitor process
|
|
113
|
+
const monitorInterval = setInterval(() => {
|
|
114
|
+
if (child.pid) {
|
|
115
|
+
try {
|
|
116
|
+
const stats = process.memoryUsage();
|
|
117
|
+
processInfo.memory = stats.heapUsed / 1024 / 1024; // MB
|
|
118
|
+
processInfo.uptime = (Date.now() - processInfo.startTime) / 1000;
|
|
119
|
+
this.emit('stats', { id: processInfo.id, stats: processInfo });
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
console.error(`Error monitoring process ${processInfo.id}:`, error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}, 1000);
|
|
126
|
+
child.on('exit', async (code) => {
|
|
127
|
+
clearInterval(monitorInterval);
|
|
128
|
+
if (code !== 0) {
|
|
129
|
+
processInfo.status = 'error';
|
|
130
|
+
processInfo.lastError = `Process exited with code ${code}`;
|
|
131
|
+
this.emit('error', { id: processInfo.id, code });
|
|
132
|
+
// Auto-restart logic
|
|
133
|
+
if (processInfo.restarts < processInfo.maxRestarts) {
|
|
134
|
+
processInfo.status = 'restarting';
|
|
135
|
+
this.emit('restart', { id: processInfo.id, attempt: processInfo.restarts + 1 });
|
|
136
|
+
await new Promise(resolve => setTimeout(resolve, processInfo.restartDelay));
|
|
137
|
+
processInfo.restarts++;
|
|
138
|
+
await this.startProcess(processInfo);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
this.emit('max-restarts', { id: processInfo.id, maxRestarts: processInfo.maxRestarts });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
processInfo.status = 'stopped';
|
|
146
|
+
}
|
|
147
|
+
this.saveConfig();
|
|
148
|
+
});
|
|
149
|
+
this.processes.set(processInfo.id, processInfo);
|
|
150
|
+
this.saveConfig();
|
|
151
|
+
this.emit('start', { id: processInfo.id, processInfo });
|
|
152
|
+
}
|
|
153
|
+
async stopx(id) {
|
|
154
|
+
const processInfo = this.processes.get(id);
|
|
155
|
+
if (!processInfo) {
|
|
156
|
+
throw new Error(`Process ${id} not found`);
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
process.kill(processInfo.pid);
|
|
160
|
+
const watcher = this.watchers.get(id);
|
|
161
|
+
if (watcher) {
|
|
162
|
+
watcher.close();
|
|
163
|
+
this.watchers.delete(id);
|
|
164
|
+
}
|
|
165
|
+
this.processes.delete(id);
|
|
166
|
+
this.saveConfig();
|
|
167
|
+
this.emit('stop', { id });
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
throw new Error(`Failed to stop process ${id}: ${error.message}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
list() {
|
|
174
|
+
return Array.from(this.processes.values());
|
|
175
|
+
}
|
|
176
|
+
monit(id) {
|
|
177
|
+
const processInfo = this.processes.get(id);
|
|
178
|
+
if (!processInfo) {
|
|
179
|
+
throw new Error(`Process ${id} not found`);
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
...processInfo,
|
|
183
|
+
logs: processInfo.logs.slice(-100) // Last 100 logs
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
log(id, lines = 100) {
|
|
187
|
+
const processInfo = this.processes.get(id);
|
|
188
|
+
if (!processInfo) {
|
|
189
|
+
throw new Error(`Process ${id} not found`);
|
|
190
|
+
}
|
|
191
|
+
const logPath = this.getLogPath(id);
|
|
192
|
+
if (!(0, fs_1.existsSync)(logPath)) {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
const logs = (0, fs_1.readFileSync)(logPath, 'utf-8').split('\n');
|
|
196
|
+
return logs.slice(-lines);
|
|
197
|
+
}
|
|
198
|
+
async restart(id) {
|
|
199
|
+
const processInfo = this.processes.get(id);
|
|
200
|
+
if (!processInfo) {
|
|
201
|
+
throw new Error(`Process ${id} not found`);
|
|
202
|
+
}
|
|
203
|
+
await this.stopx(id);
|
|
204
|
+
processInfo.restarts++;
|
|
205
|
+
await this.startx(processInfo.path, { name: processInfo.name, watch: true });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
exports.processManager = new ProcessManager();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neex",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "The Modern Build System for Polyrepo-in-Monorepo Architecture",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -29,15 +29,19 @@
|
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"chalk": "^4.1.2",
|
|
32
|
+
"chokidar": "^3.5.3",
|
|
32
33
|
"commander": "^9.4.0",
|
|
33
34
|
"figlet": "^1.8.1",
|
|
34
35
|
"figures": "^3.2.0",
|
|
35
36
|
"gradient-string": "^3.0.0",
|
|
36
37
|
"npm-run-path": "^4.0.1",
|
|
37
38
|
"p-map": "^4.0.0",
|
|
38
|
-
"string-width": "^4.2.3"
|
|
39
|
+
"string-width": "^4.2.3",
|
|
40
|
+
"ts-node": "^10.9.1",
|
|
41
|
+
"tsconfig-paths": "^4.2.0"
|
|
39
42
|
},
|
|
40
43
|
"devDependencies": {
|
|
44
|
+
"@types/chokidar": "^2.1.7",
|
|
41
45
|
"@types/figlet": "^1.7.0",
|
|
42
46
|
"@types/jest": "^29.2.3",
|
|
43
47
|
"@types/node": "^18.11.9",
|