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 CHANGED
@@ -1,12 +1,4 @@
1
- <div align="center">
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
  [![Download Count](https://img.shields.io/npm/dt/neex.svg?style=for-the-badge&labelColor=000000&color=0066FF&borderRadius=8)](https://www.npmjs.com/package/neex)
15
7
  [![MIT License](https://img.shields.io/badge/license-MIT-0066FF.svg?style=for-the-badge&labelColor=000000&borderRadius=8)](https://github.com/neexjs/blob/main/LICENSE)
16
8
  [![GitHub](https://img.shields.io/badge/GitHub-Neex-0066FF.svg?style=for-the-badge&logo=github&labelColor=000000&logoWidth=20&borderRadius=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`, `runx`) or sequence (`s`, `run`)
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
- - `runx` (alias: `p`) - Run in **parallel** (default)
55
- - `run` (alias: `s`) - Run **sequentially**
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
- ### Examples
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 "echo Step 1" "echo Step 2" "echo Step 3"
78
+ neex s "npm install" "npm run build"
65
79
 
66
- # Parallel with sequential flag
67
- neex p -q "echo Step 1" "echo Step 2" "echo Step 3"
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
- ```bash
147
- # Dev servers
148
- neex p "cd frontend && npm dev" "cd api && npm dev"
149
-
150
- # Monorepo build
151
- neex p -m 2 "npm run build:ui" "npm run build:api"
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
- # Deploy pipeline
154
- neex s -s "npm test" "npm run build" "npm run deploy"
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@4.0.0", "", {}, "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w=="],
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
- "istanbul-lib-instrument/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
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
- // Main command for sequential execution (similar to run-s)
24
+ // Development command for Express.js projects
20
25
  program
21
- .command('run <commands...>')
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('runx <commands...>', { isDefault: true })
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
- // Add a new servers command specifically optimized for running web servers
228
+ // Process Management Commands
91
229
  program
92
- .command('servers <commands...>')
93
- .alias('srv')
94
- .description('Run multiple servers with optimized output for API, frontend, etc.')
95
- .option('-c, --no-color', 'Disable colored output')
96
- .option('-t, --no-timing', 'Hide timing information')
97
- .option('-p, --no-prefix', 'Hide command prefix')
98
- .option('-s, --stop-on-error', 'Stop when any server crashes')
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
- console.log(chalk_1.default.blue(`${figures_1.default.info} Starting servers in parallel mode...`));
104
- await (0, index_js_1.run)(commands, {
105
- parallel: true,
106
- maxParallel: options.maxParallel,
107
- color: options.color,
108
- showTiming: options.timing,
109
- prefix: options.prefix,
110
- stopOnError: options.stopOnError,
111
- printOutput: true,
112
- registerCleanup: (cleanup) => { cleanupRunner = cleanup; },
113
- groupOutput: options.groupOutput,
114
- isServerMode: true // Special flag for server mode formatting
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} Server Error: ${error.message}`));
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 server error occurred`));
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.5",
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",