neex 0.2.6 → 0.2.8

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,5 +1,12 @@
1
- # Neex v0.2.6
2
-
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.8
3
10
  ### 🚀 Neex: The Modern Build System for Polyrepo-in-Monorepo Architecture
4
11
 
5
12
  [![NPM version](https://img.shields.io/npm/v/neex.svg?style=for-the-badge&labelColor=000000&color=0066FF&borderRadius=8)](https://www.npmjs.com/package/neex)
@@ -7,6 +14,8 @@
7
14
  [![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)
8
15
  [![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)
9
16
 
17
+ </div>
18
+
10
19
  ## 🎯 Overview
11
20
 
12
21
  next + express = neex 🌱
package/bun.lock CHANGED
@@ -6,6 +6,7 @@
6
6
  "dependencies": {
7
7
  "chalk": "^4.1.2",
8
8
  "chokidar": "^3.5.3",
9
+ "cli-table3": "^0.6.5",
9
10
  "commander": "^9.4.0",
10
11
  "figlet": "^1.8.1",
11
12
  "figures": "^3.2.0",
@@ -14,6 +15,7 @@
14
15
  "p-map": "^4.0.0",
15
16
  "string-width": "^4.2.3",
16
17
  "ts-node": "^10.9.1",
18
+ "ts-node-dev": "^2.0.0",
17
19
  "tsconfig-paths": "^4.2.0",
18
20
  },
19
21
  "devDependencies": {
@@ -98,6 +100,8 @@
98
100
 
99
101
  "@bcoe/v8-coverage": ["@bcoe/v8-coverage@0.2.3", "", {}, "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="],
100
102
 
103
+ "@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="],
104
+
101
105
  "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
102
106
 
103
107
  "@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=="],
@@ -182,6 +186,10 @@
182
186
 
183
187
  "@types/stack-utils": ["@types/stack-utils@2.0.3", "", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="],
184
188
 
189
+ "@types/strip-bom": ["@types/strip-bom@3.0.0", "", {}, "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ=="],
190
+
191
+ "@types/strip-json-comments": ["@types/strip-json-comments@0.0.30", "", {}, "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ=="],
192
+
185
193
  "@types/tinycolor2": ["@types/tinycolor2@1.4.6", "", {}, "sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw=="],
186
194
 
187
195
  "@types/yargs": ["@types/yargs@17.0.33", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA=="],
@@ -252,6 +260,8 @@
252
260
 
253
261
  "clean-stack": ["clean-stack@2.2.0", "", {}, "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="],
254
262
 
263
+ "cli-table3": ["cli-table3@0.6.5", "", { "dependencies": { "string-width": "^4.2.0" }, "optionalDependencies": { "@colors/colors": "1.5.0" } }, "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ=="],
264
+
255
265
  "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
256
266
 
257
267
  "co": ["co@4.6.0", "", {}, "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ=="],
@@ -286,6 +296,8 @@
286
296
 
287
297
  "diff-sequences": ["diff-sequences@29.6.3", "", {}, "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q=="],
288
298
 
299
+ "dynamic-dedupe": ["dynamic-dedupe@0.3.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ=="],
300
+
289
301
  "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": "bin/cli.js" }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="],
290
302
 
291
303
  "electron-to-chromium": ["electron-to-chromium@1.5.152", "", {}, "sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg=="],
@@ -486,6 +498,8 @@
486
498
 
487
499
  "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
488
500
 
501
+ "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
502
+
489
503
  "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
490
504
 
491
505
  "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
@@ -548,6 +562,8 @@
548
562
 
549
563
  "resolve.exports": ["resolve.exports@2.0.3", "", {}, "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A=="],
550
564
 
565
+ "rimraf": ["rimraf@2.7.1", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w=="],
566
+
551
567
  "semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
552
568
 
553
569
  "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
@@ -578,7 +594,7 @@
578
594
 
579
595
  "strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
580
596
 
581
- "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
597
+ "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
582
598
 
583
599
  "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
584
600
 
@@ -594,10 +610,16 @@
594
610
 
595
611
  "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
596
612
 
613
+ "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="],
614
+
597
615
  "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=="],
598
616
 
599
617
  "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
618
 
619
+ "ts-node-dev": ["ts-node-dev@2.0.0", "", { "dependencies": { "chokidar": "^3.5.1", "dynamic-dedupe": "^0.3.0", "minimist": "^1.2.6", "mkdirp": "^1.0.4", "resolve": "^1.0.0", "rimraf": "^2.6.1", "source-map-support": "^0.5.12", "tree-kill": "^1.2.2", "ts-node": "^10.4.0", "tsconfig": "^7.0.0" }, "peerDependencies": { "node-notifier": "*", "typescript": "*" }, "optionalPeers": ["node-notifier"], "bin": { "ts-node-dev": "lib/bin.js", "tsnd": "lib/bin.js" } }, "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w=="],
620
+
621
+ "tsconfig": ["tsconfig@7.0.0", "", { "dependencies": { "@types/strip-bom": "^3.0.0", "@types/strip-json-comments": "0.0.30", "strip-bom": "^3.0.0", "strip-json-comments": "^2.0.0" } }, "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw=="],
622
+
601
623
  "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
624
 
603
625
  "type-detect": ["type-detect@4.0.8", "", {}, "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="],
@@ -624,6 +646,8 @@
624
646
 
625
647
  "write-file-atomic": ["write-file-atomic@4.0.2", "", { "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" } }, "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg=="],
626
648
 
649
+ "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
650
+
627
651
  "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
628
652
 
629
653
  "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
@@ -652,6 +676,8 @@
652
676
 
653
677
  "gradient-string/chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="],
654
678
 
679
+ "jest-config/strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
680
+
655
681
  "jest-runtime/strip-bom": ["strip-bom@4.0.0", "", {}, "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w=="],
656
682
 
657
683
  "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
package/dist/src/cli.js CHANGED
@@ -26,8 +26,12 @@ function cli() {
26
26
  .command('dev <entry>')
27
27
  .description('Run Express.js project in development mode with TypeScript support')
28
28
  .option('-p, --port <number>', 'Port to run the server on', '3000')
29
- .option('-w, --watch <path>', 'Path to watch for changes', 'src')
29
+ .option('-w, --watch <paths...>', 'Paths to watch for changes', ['src'])
30
+ .option('-i, --ignore <paths...>', 'Paths to ignore', ['node_modules', 'dist', '.git'])
31
+ .option('-e, --ext <extensions...>', 'File extensions to watch', ['ts', 'js', 'json'])
32
+ .option('-d, --delay <number>', 'Delay before restarting in milliseconds', '1000')
30
33
  .option('-c, --no-color', 'Disable colored output')
34
+ .option('--no-clear', 'Disable screen clearing on restart')
31
35
  .action(async (entry, options) => {
32
36
  try {
33
37
  const entryPath = (0, path_1.resolve)(process.cwd(), entry);
@@ -35,24 +39,13 @@ function cli() {
35
39
  throw new Error(`Entry file ${entry} not found`);
36
40
  }
37
41
  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
42
+ let server = null;
43
+ let isRestarting = false;
44
+ let restartTimer = null;
45
+ const startServer = () => {
46
+ if (server) {
47
+ server.kill();
46
48
  }
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
49
  server = (0, child_process_1.spawn)('ts-node', [
57
50
  '-r', 'tsconfig-paths/register',
58
51
  entryPath
@@ -60,17 +53,73 @@ function cli() {
60
53
  stdio: 'inherit',
61
54
  env: {
62
55
  ...process.env,
63
- PORT: options.port
56
+ PORT: options.port,
57
+ NODE_ENV: 'development'
64
58
  }
65
59
  });
60
+ server.on('error', (err) => {
61
+ console.error(chalk_1.default.red(`${figures_1.default.cross} Server error: ${err.message}`));
62
+ });
63
+ server.on('exit', (code) => {
64
+ if (code !== 0 && !isRestarting) {
65
+ console.error(chalk_1.default.red(`${figures_1.default.cross} Server crashed with code ${code}`));
66
+ }
67
+ });
68
+ };
69
+ // Initial server start
70
+ startServer();
71
+ // Setup file watching with chokidar
72
+ const watcher = (0, chokidar_1.watch)(options.watch, {
73
+ ignored: [
74
+ ...options.ignore,
75
+ /(^|[\/\\])\../,
76
+ '**/*.map' // Ignore source maps
77
+ ],
78
+ persistent: true,
79
+ ignoreInitial: true,
80
+ awaitWriteFinish: {
81
+ stabilityThreshold: 300,
82
+ pollInterval: 100
83
+ }
84
+ });
85
+ // Handle file changes
86
+ watcher.on('change', (path) => {
87
+ var _a;
88
+ const ext = (_a = path.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
89
+ if (!ext || !options.ext.includes(ext)) {
90
+ return;
91
+ }
92
+ if (restartTimer) {
93
+ clearTimeout(restartTimer);
94
+ }
95
+ isRestarting = true;
96
+ restartTimer = setTimeout(() => {
97
+ if (options.clear) {
98
+ process.stdout.write('\x1Bc'); // Clear screen
99
+ }
100
+ console.log(chalk_1.default.yellow(`${figures_1.default.info} File ${path} changed. Restarting...`));
101
+ startServer();
102
+ isRestarting = false;
103
+ }, parseInt(options.delay));
66
104
  });
105
+ // Handle cleanup
67
106
  cleanupRunner = () => {
68
- server.kill();
107
+ if (server) {
108
+ server.kill();
109
+ }
110
+ if (restartTimer) {
111
+ clearTimeout(restartTimer);
112
+ }
69
113
  watcher.close();
70
114
  };
71
- server.on('error', (err) => {
72
- console.error(chalk_1.default.red(`${figures_1.default.cross} Server error: ${err.message}`));
73
- process.exit(1);
115
+ // Handle process signals
116
+ process.on('SIGINT', () => {
117
+ cleanupRunner === null || cleanupRunner === void 0 ? void 0 : cleanupRunner();
118
+ process.exit(0);
119
+ });
120
+ process.on('SIGTERM', () => {
121
+ cleanupRunner === null || cleanupRunner === void 0 ? void 0 : cleanupRunner();
122
+ process.exit(0);
74
123
  });
75
124
  }
76
125
  catch (error) {
@@ -118,31 +167,56 @@ function cli() {
118
167
  });
119
168
  // Start command for production
120
169
  program
121
- .command('start <entry>')
122
- .description('Start Express.js project in production mode')
170
+ .command('start')
171
+ .description('Start the built application in production mode')
123
172
  .option('-p, --port <number>', 'Port to run the server on', '3000')
124
- .action(async (entry, options) => {
173
+ .option('-o, --outDir <dir>', 'Output directory', 'dist')
174
+ .option('-e, --entry <file>', 'Entry file name', 'index.js')
175
+ .action(async (options) => {
125
176
  try {
126
- const entryPath = (0, path_1.resolve)(process.cwd(), entry);
177
+ const outDir = options.outDir;
178
+ const entryFile = options.entry;
179
+ const entryPath = (0, path_1.resolve)(process.cwd(), outDir, entryFile);
127
180
  if (!(0, fs_1.existsSync)(entryPath)) {
128
- throw new Error(`Entry file ${entry} not found`);
181
+ console.log(chalk_1.default.yellow(`${figures_1.default.warning} Build not found. Building project first...`));
182
+ // Run build command first
183
+ const build = (0, child_process_1.spawn)('tsc', [
184
+ '--outDir', outDir
185
+ ], {
186
+ stdio: 'inherit'
187
+ });
188
+ build.on('close', (code) => {
189
+ if (code === 0) {
190
+ console.log(chalk_1.default.green(`${figures_1.default.tick} Build completed successfully`));
191
+ startServer();
192
+ }
193
+ else {
194
+ console.error(chalk_1.default.red(`${figures_1.default.cross} Build failed with code ${code}`));
195
+ process.exit(code !== null && code !== void 0 ? code : 1);
196
+ }
197
+ });
198
+ }
199
+ else {
200
+ startServer();
201
+ }
202
+ function startServer() {
203
+ console.log(chalk_1.default.blue(`${figures_1.default.info} Starting production server...`));
204
+ const server = (0, child_process_1.spawn)('node', [entryPath], {
205
+ stdio: 'inherit',
206
+ env: {
207
+ ...process.env,
208
+ PORT: options.port,
209
+ NODE_ENV: 'production'
210
+ }
211
+ });
212
+ cleanupRunner = () => {
213
+ server.kill();
214
+ };
215
+ server.on('error', (err) => {
216
+ console.error(chalk_1.default.red(`${figures_1.default.cross} Server error: ${err.message}`));
217
+ process.exit(1);
218
+ });
129
219
  }
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
220
  }
147
221
  catch (error) {
148
222
  if (error instanceof Error) {
@@ -227,24 +301,26 @@ function cli() {
227
301
  });
228
302
  // Process Management Commands
229
303
  program
230
- .command('startx <path>')
304
+ .command('startx <command>')
231
305
  .description('Start a process with monitoring and auto-restart')
232
306
  .option('-n, --name <name>', 'Process name')
233
307
  .option('-w, --watch', 'Watch for file changes and auto-restart')
234
308
  .option('-r, --max-restarts <number>', 'Maximum number of restart attempts', '5')
235
309
  .option('-d, --restart-delay <number>', 'Delay between restarts in milliseconds', '1000')
236
- .action(async (path, options) => {
310
+ .option('-c, --cwd <path>', 'Working directory for the process')
311
+ .action(async (command, options) => {
237
312
  try {
238
- const process = await process_manager_js_1.processManager.startx(path, {
313
+ const process = await process_manager_js_1.processManager.startx(command, {
239
314
  name: options.name,
240
315
  watch: options.watch,
241
316
  maxRestarts: parseInt(options.maxRestarts),
242
- restartDelay: parseInt(options.restartDelay)
317
+ restartDelay: parseInt(options.restartDelay),
318
+ cwd: options.cwd
243
319
  });
244
320
  console.log(chalk_1.default.green(`${figures_1.default.tick} Process started successfully`));
245
- console.log(chalk_1.default.blue(`ID: ${process.id}`));
246
321
  console.log(chalk_1.default.blue(`Name: ${process.name}`));
247
322
  console.log(chalk_1.default.blue(`PID: ${process.pid}`));
323
+ console.log(chalk_1.default.blue(`Command: ${process.command}`));
248
324
  console.log(chalk_1.default.blue(`Max Restarts: ${process.maxRestarts}`));
249
325
  console.log(chalk_1.default.blue(`Restart Delay: ${process.restartDelay}ms`));
250
326
  }
@@ -259,12 +335,12 @@ function cli() {
259
335
  }
260
336
  });
261
337
  program
262
- .command('stopx <id>')
338
+ .command('stopx <name>')
263
339
  .description('Stop a running process')
264
340
  .option('-f, --force', 'Force stop the process')
265
- .action(async (id, options) => {
341
+ .action(async (name, options) => {
266
342
  try {
267
- await process_manager_js_1.processManager.stopx(id);
343
+ await process_manager_js_1.processManager.stopx(name);
268
344
  console.log(chalk_1.default.green(`${figures_1.default.tick} Process stopped successfully`));
269
345
  }
270
346
  catch (error) {
@@ -283,81 +359,42 @@ function cli() {
283
359
  .option('-a, --all', 'Show all processes including stopped ones')
284
360
  .option('-j, --json', 'Output in JSON format')
285
361
  .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;
362
+ try {
363
+ if (options.json) {
364
+ const processes = Array.from(process_manager_js_1.processManager.list());
365
+ console.log(JSON.stringify(processes, null, 2));
366
+ return;
367
+ }
368
+ console.log(process_manager_js_1.processManager.list());
295
369
  }
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)}`);
370
+ catch (error) {
371
+ if (error instanceof Error) {
372
+ console.error(chalk_1.default.red(`${figures_1.default.cross} Error: ${error.message}`));
310
373
  }
311
- });
374
+ else {
375
+ console.error(chalk_1.default.red(`${figures_1.default.cross} An unknown error occurred`));
376
+ }
377
+ process.exit(1);
378
+ }
312
379
  });
313
380
  program
314
- .command('monit <id>')
315
- .description('Monitor a specific process')
381
+ .command('monit <name>')
382
+ .description('Monitor a process in real-time')
316
383
  .option('-i, --interval <number>', 'Update interval in milliseconds', '1000')
317
- .action((id, options) => {
384
+ .action((name, options) => {
318
385
  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)}`);
386
+ const interval = parseInt(options.interval);
387
+ if (isNaN(interval) || interval < 100) {
388
+ throw new Error('Interval must be a number greater than 100ms');
330
389
  }
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
390
  // Start real-time monitoring
344
- const interval = setInterval(() => {
391
+ const updateDisplay = () => {
345
392
  try {
346
- const updatedProcess = process_manager_js_1.processManager.monit(id);
393
+ const { table, logs } = process_manager_js_1.processManager.monit(name);
347
394
  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 => {
395
+ console.log(table);
396
+ console.log(chalk_1.default.blue('\nRecent Logs:'));
397
+ logs.forEach(log => {
361
398
  if (log.includes('error') || log.includes('Error')) {
362
399
  console.log(chalk_1.default.red(log));
363
400
  }
@@ -370,14 +407,15 @@ function cli() {
370
407
  });
371
408
  }
372
409
  catch (error) {
373
- clearInterval(interval);
410
+ clearInterval(monitorInterval);
374
411
  console.error(chalk_1.default.red(`${figures_1.default.cross} Error monitoring process: ${error}`));
375
412
  process.exit(1);
376
413
  }
377
- }, parseInt(options.interval));
378
- // Handle cleanup
414
+ };
415
+ const monitorInterval = setInterval(updateDisplay, interval);
416
+ updateDisplay(); // Initial display
379
417
  process.on('SIGINT', () => {
380
- clearInterval(interval);
418
+ clearInterval(monitorInterval);
381
419
  process.exit(0);
382
420
  });
383
421
  }
@@ -392,31 +430,29 @@ function cli() {
392
430
  }
393
431
  });
394
432
  program
395
- .command('log <id>')
433
+ .command('log <name>')
396
434
  .description('View process logs')
397
- .option('-l, --lines <number>', 'Number of lines to show', '100')
398
435
  .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) => {
436
+ .option('-e, --errors', 'Show only errors')
437
+ .option('-w, --warnings', 'Show only warnings')
438
+ .option('-l, --lines <number>', 'Number of lines to show', '100')
439
+ .action((name, options) => {
402
440
  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') ||
441
+ const lines = parseInt(options.lines);
442
+ if (isNaN(lines) || lines < 1) {
443
+ throw new Error('Lines must be a positive number');
444
+ }
445
+ const logs = process_manager_js_1.processManager.log(name, lines);
446
+ let filteredLogs = logs;
447
+ if (options.errors) {
448
+ filteredLogs = logs.filter(log => log.toLowerCase().includes('error') ||
406
449
  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
450
  }
411
- if (options.warn) {
412
- const warnLogs = logs.filter(log => log.toLowerCase().includes('warn') ||
451
+ else if (options.warnings) {
452
+ filteredLogs = logs.filter(log => log.toLowerCase().includes('warn') ||
413
453
  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
454
  }
418
- console.log(chalk_1.default.blue(`${figures_1.default.info} Process Logs:`));
419
- logs.forEach(log => {
455
+ filteredLogs.forEach(log => {
420
456
  if (log.includes('error') || log.includes('Error')) {
421
457
  console.log(chalk_1.default.red(log));
422
458
  }
@@ -428,11 +464,11 @@ function cli() {
428
464
  }
429
465
  });
430
466
  if (options.follow) {
431
- const watcher = (0, chokidar_1.watch)(process_manager_js_1.processManager.getLogPath(id), {
467
+ const watcher = (0, chokidar_1.watch)(process_manager_js_1.processManager.getLogPath(name), {
432
468
  persistent: true
433
469
  });
434
470
  watcher.on('change', () => {
435
- const newLogs = process_manager_js_1.processManager.log(id, 1);
471
+ const newLogs = process_manager_js_1.processManager.log(name, 1);
436
472
  if (newLogs.length > 0) {
437
473
  const log = newLogs[0];
438
474
  if (log.includes('error') || log.includes('Error')) {
@@ -1,18 +1,24 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.processManager = void 0;
4
7
  const child_process_1 = require("child_process");
5
8
  const chokidar_1 = require("chokidar");
6
9
  const fs_1 = require("fs");
7
10
  const path_1 = require("path");
11
+ const chalk_1 = __importDefault(require("chalk"));
8
12
  const events_1 = require("events");
13
+ const cli_table3_1 = __importDefault(require("cli-table3"));
14
+ const child_process_2 = require("child_process");
9
15
  class ProcessManager extends events_1.EventEmitter {
10
16
  constructor() {
11
17
  super();
12
18
  this.processes = new Map();
13
19
  this.watchers = new Map();
14
20
  this.defaultMaxRestarts = 5;
15
- this.defaultRestartDelay = 1000; // 1 second
21
+ this.defaultRestartDelay = 1000;
16
22
  this.logDir = (0, path_1.resolve)(process.cwd(), '.neex-logs');
17
23
  this.configFile = (0, path_1.resolve)(process.cwd(), '.neex-config.json');
18
24
  this.initialize();
@@ -33,27 +39,26 @@ class ProcessManager extends events_1.EventEmitter {
33
39
  const config = Object.fromEntries(this.processes);
34
40
  (0, fs_1.writeFileSync)(this.configFile, JSON.stringify(config, null, 2));
35
41
  }
36
- generateId() {
37
- return Math.random().toString(36).substring(2, 15);
42
+ generateName(command) {
43
+ const baseName = command.split(' ')[0].replace(/[^a-zA-Z0-9]/g, '');
44
+ const timestamp = Date.now().toString(36);
45
+ return `${baseName}-${timestamp}`;
38
46
  }
39
- getLogPath(id) {
40
- return (0, path_1.join)(this.logDir, `${id}.log`);
47
+ getLogPath(name) {
48
+ return (0, path_1.join)(this.logDir, `${name}.log`);
41
49
  }
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`);
50
+ async startx(command, options = {}) {
51
+ const name = options.name || this.generateName(command);
52
+ const cwd = options.cwd || process.cwd();
53
+ if (this.processes.has(name)) {
54
+ throw new Error(`Process with name ${name} already exists`);
48
55
  }
49
56
  const processInfo = {
50
- id,
51
57
  name,
52
58
  pid: 0,
53
59
  status: 'stopped',
54
60
  startTime: Date.now(),
55
- path: fullPath,
56
- command: `node ${fullPath}`,
61
+ command,
57
62
  logs: [],
58
63
  memory: 0,
59
64
  cpu: 0,
@@ -61,7 +66,8 @@ class ProcessManager extends events_1.EventEmitter {
61
66
  restarts: 0,
62
67
  maxRestarts: options.maxRestarts || this.defaultMaxRestarts,
63
68
  restartDelay: options.restartDelay || this.defaultRestartDelay,
64
- watch: options.watch
69
+ watch: options.watch,
70
+ cwd
65
71
  };
66
72
  try {
67
73
  await this.startProcess(processInfo);
@@ -70,56 +76,60 @@ class ProcessManager extends events_1.EventEmitter {
70
76
  catch (error) {
71
77
  processInfo.status = 'error';
72
78
  processInfo.lastError = error.message;
73
- this.processes.set(id, processInfo);
79
+ this.processes.set(name, processInfo);
74
80
  this.saveConfig();
75
81
  throw error;
76
82
  }
77
83
  }
78
84
  async startProcess(processInfo) {
79
85
  var _a, _b;
80
- const child = (0, child_process_1.spawn)('node', [processInfo.path], {
86
+ const [cmd, ...args] = processInfo.command.split(' ');
87
+ const child = (0, child_process_1.spawn)(cmd, args, {
81
88
  stdio: ['ignore', 'pipe', 'pipe'],
82
- env: { ...process.env, NODE_ENV: 'production' }
89
+ env: { ...process.env, NODE_ENV: 'production' },
90
+ cwd: processInfo.cwd,
91
+ shell: true
83
92
  });
84
93
  processInfo.pid = child.pid || 0;
85
94
  processInfo.status = 'running';
86
95
  processInfo.startTime = Date.now();
87
96
  // Setup logging
88
- const logStream = (0, fs_1.writeFileSync)(this.getLogPath(processInfo.id), '', { flag: 'a' });
97
+ (0, fs_1.writeFileSync)(this.getLogPath(processInfo.name), '', { flag: 'a' });
89
98
  (_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
90
99
  const log = data.toString();
91
100
  processInfo.logs.push(log);
92
- (0, fs_1.writeFileSync)(this.getLogPath(processInfo.id), log, { flag: 'a' });
93
- this.emit('log', { id: processInfo.id, log });
101
+ (0, fs_1.writeFileSync)(this.getLogPath(processInfo.name), log, { flag: 'a' });
102
+ this.emit('log', { name: processInfo.name, log });
94
103
  });
95
104
  (_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
96
105
  const log = data.toString();
97
106
  processInfo.logs.push(log);
98
- (0, fs_1.writeFileSync)(this.getLogPath(processInfo.id), log, { flag: 'a' });
99
- this.emit('error', { id: processInfo.id, log });
107
+ (0, fs_1.writeFileSync)(this.getLogPath(processInfo.name), log, { flag: 'a' });
108
+ this.emit('error', { name: processInfo.name, log });
100
109
  });
101
110
  // Setup monitoring
102
- if (processInfo.watch) {
103
- const watcher = (0, chokidar_1.watch)(processInfo.path, {
111
+ if (processInfo.watch && processInfo.cwd) {
112
+ const watcher = (0, chokidar_1.watch)(processInfo.cwd, {
104
113
  ignored: /(^|[\/\\])\../,
105
114
  persistent: true
106
115
  });
107
116
  watcher.on('change', () => {
108
- this.restart(processInfo.id);
117
+ this.restart(processInfo.name);
109
118
  });
110
- this.watchers.set(processInfo.id, watcher);
119
+ this.watchers.set(processInfo.name, watcher);
111
120
  }
112
121
  // Monitor process
113
122
  const monitorInterval = setInterval(() => {
114
123
  if (child.pid) {
115
124
  try {
116
- const stats = process.memoryUsage();
117
- processInfo.memory = stats.heapUsed / 1024 / 1024; // MB
125
+ const stats = this.getProcessStats(child.pid);
126
+ processInfo.memory = stats.memory;
127
+ processInfo.cpu = stats.cpu;
118
128
  processInfo.uptime = (Date.now() - processInfo.startTime) / 1000;
119
- this.emit('stats', { id: processInfo.id, stats: processInfo });
129
+ this.emit('stats', { name: processInfo.name, stats: processInfo });
120
130
  }
121
131
  catch (error) {
122
- console.error(`Error monitoring process ${processInfo.id}:`, error);
132
+ console.error(`Error monitoring process ${processInfo.name}:`, error);
123
133
  }
124
134
  }
125
135
  }, 1000);
@@ -128,17 +138,16 @@ class ProcessManager extends events_1.EventEmitter {
128
138
  if (code !== 0) {
129
139
  processInfo.status = 'error';
130
140
  processInfo.lastError = `Process exited with code ${code}`;
131
- this.emit('error', { id: processInfo.id, code });
132
- // Auto-restart logic
141
+ this.emit('error', { name: processInfo.name, code });
133
142
  if (processInfo.restarts < processInfo.maxRestarts) {
134
143
  processInfo.status = 'restarting';
135
- this.emit('restart', { id: processInfo.id, attempt: processInfo.restarts + 1 });
144
+ this.emit('restart', { name: processInfo.name, attempt: processInfo.restarts + 1 });
136
145
  await new Promise(resolve => setTimeout(resolve, processInfo.restartDelay));
137
146
  processInfo.restarts++;
138
147
  await this.startProcess(processInfo);
139
148
  }
140
149
  else {
141
- this.emit('max-restarts', { id: processInfo.id, maxRestarts: processInfo.maxRestarts });
150
+ this.emit('max-restarts', { name: processInfo.name, maxRestarts: processInfo.maxRestarts });
142
151
  }
143
152
  }
144
153
  else {
@@ -146,63 +155,104 @@ class ProcessManager extends events_1.EventEmitter {
146
155
  }
147
156
  this.saveConfig();
148
157
  });
149
- this.processes.set(processInfo.id, processInfo);
158
+ this.processes.set(processInfo.name, processInfo);
150
159
  this.saveConfig();
151
- this.emit('start', { id: processInfo.id, processInfo });
160
+ this.emit('start', { name: processInfo.name, processInfo });
152
161
  }
153
- async stopx(id) {
154
- const processInfo = this.processes.get(id);
162
+ getProcessStats(pid) {
163
+ try {
164
+ const stats = (0, child_process_2.execSync)(`ps -p ${pid} -o %mem,%cpu`).toString().split('\n')[1].trim().split(/\s+/);
165
+ return {
166
+ memory: parseFloat(stats[0]),
167
+ cpu: parseFloat(stats[1])
168
+ };
169
+ }
170
+ catch (_a) {
171
+ return { memory: 0, cpu: 0 };
172
+ }
173
+ }
174
+ async stopx(name) {
175
+ const processInfo = this.processes.get(name);
155
176
  if (!processInfo) {
156
- throw new Error(`Process ${id} not found`);
177
+ throw new Error(`Process ${name} not found`);
157
178
  }
158
179
  try {
159
180
  process.kill(processInfo.pid);
160
- const watcher = this.watchers.get(id);
181
+ const watcher = this.watchers.get(name);
161
182
  if (watcher) {
162
183
  watcher.close();
163
- this.watchers.delete(id);
184
+ this.watchers.delete(name);
164
185
  }
165
- this.processes.delete(id);
186
+ this.processes.delete(name);
166
187
  this.saveConfig();
167
- this.emit('stop', { id });
188
+ this.emit('stop', { name });
168
189
  }
169
190
  catch (error) {
170
- throw new Error(`Failed to stop process ${id}: ${error.message}`);
191
+ throw new Error(`Failed to stop process ${name}: ${error.message}`);
171
192
  }
172
193
  }
173
194
  list() {
174
- return Array.from(this.processes.values());
195
+ const table = new cli_table3_1.default({
196
+ head: ['Name', 'Status', 'PID', 'Memory', 'CPU', 'Uptime', 'Restarts'],
197
+ style: { head: ['cyan'] }
198
+ });
199
+ Array.from(this.processes.values()).forEach(process => {
200
+ const statusColor = process.status === 'running' ? 'green' :
201
+ process.status === 'error' ? 'red' :
202
+ process.status === 'restarting' ? 'yellow' : 'gray';
203
+ table.push([
204
+ process.name,
205
+ chalk_1.default[statusColor](process.status),
206
+ process.pid || '-',
207
+ `${process.memory.toFixed(2)}MB`,
208
+ `${process.cpu.toFixed(1)}%`,
209
+ `${Math.floor(process.uptime)}s`,
210
+ `${process.restarts}/${process.maxRestarts}`
211
+ ]);
212
+ });
213
+ return table.toString();
175
214
  }
176
- monit(id) {
177
- const processInfo = this.processes.get(id);
215
+ monit(name) {
216
+ const processInfo = this.processes.get(name);
178
217
  if (!processInfo) {
179
- throw new Error(`Process ${id} not found`);
218
+ throw new Error(`Process ${name} not found`);
219
+ }
220
+ const table = new cli_table3_1.default({
221
+ style: { head: ['cyan'] }
222
+ });
223
+ table.push(['Name', processInfo.name], ['Status', chalk_1.default[processInfo.status === 'running' ? 'green' : 'red'](processInfo.status)], ['PID', processInfo.pid.toString()], ['Memory', `${processInfo.memory.toFixed(2)}MB`], ['CPU', `${processInfo.cpu.toFixed(1)}%`], ['Uptime', `${Math.floor(processInfo.uptime)}s`], ['Restarts', `${processInfo.restarts}/${processInfo.maxRestarts}`]);
224
+ if (processInfo.lastError) {
225
+ table.push(['Last Error', chalk_1.default.red(processInfo.lastError)]);
180
226
  }
181
227
  return {
182
- ...processInfo,
183
- logs: processInfo.logs.slice(-100) // Last 100 logs
228
+ table: table.toString(),
229
+ logs: processInfo.logs.slice(-100)
184
230
  };
185
231
  }
186
- log(id, lines = 100) {
187
- const processInfo = this.processes.get(id);
232
+ log(name, lines = 100) {
233
+ const processInfo = this.processes.get(name);
188
234
  if (!processInfo) {
189
- throw new Error(`Process ${id} not found`);
235
+ throw new Error(`Process ${name} not found`);
190
236
  }
191
- const logPath = this.getLogPath(id);
237
+ const logPath = this.getLogPath(name);
192
238
  if (!(0, fs_1.existsSync)(logPath)) {
193
239
  return [];
194
240
  }
195
241
  const logs = (0, fs_1.readFileSync)(logPath, 'utf-8').split('\n');
196
242
  return logs.slice(-lines);
197
243
  }
198
- async restart(id) {
199
- const processInfo = this.processes.get(id);
244
+ async restart(name) {
245
+ const processInfo = this.processes.get(name);
200
246
  if (!processInfo) {
201
- throw new Error(`Process ${id} not found`);
247
+ throw new Error(`Process ${name} not found`);
202
248
  }
203
- await this.stopx(id);
249
+ await this.stopx(name);
204
250
  processInfo.restarts++;
205
- await this.startx(processInfo.path, { name: processInfo.name, watch: true });
251
+ await this.startx(processInfo.command, {
252
+ name: processInfo.name,
253
+ watch: true,
254
+ cwd: processInfo.cwd
255
+ });
206
256
  }
207
257
  }
208
258
  exports.processManager = new ProcessManager();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neex",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
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",
@@ -30,14 +30,17 @@
30
30
  "dependencies": {
31
31
  "chalk": "^4.1.2",
32
32
  "chokidar": "^3.5.3",
33
+ "cli-table3": "^0.6.5",
33
34
  "commander": "^9.4.0",
34
35
  "figlet": "^1.8.1",
35
36
  "figures": "^3.2.0",
36
37
  "gradient-string": "^3.0.0",
38
+ "node-notifier": "^10.0.1",
37
39
  "npm-run-path": "^4.0.1",
38
40
  "p-map": "^4.0.0",
39
41
  "string-width": "^4.2.3",
40
42
  "ts-node": "^10.9.1",
43
+ "ts-node-dev": "^2.0.0",
41
44
  "tsconfig-paths": "^4.2.0"
42
45
  },
43
46
  "devDependencies": {