feat(cli): Enhance CLI with new process management commands
This commit is contained in:
		@@ -1,5 +1,12 @@
 | 
			
		||||
# Changelog
 | 
			
		||||
 | 
			
		||||
## 2025-03-04 - 1.5.0 - feat(cli)
 | 
			
		||||
Enhance CLI with new process management commands
 | 
			
		||||
 | 
			
		||||
- Added comprehensive CLI commands for process management including start, stop, restart, list, describe and logs.
 | 
			
		||||
- Implemented memory string parsing for process memory limits.
 | 
			
		||||
- Enhanced CLI output with formatted table listings for active processes.
 | 
			
		||||
 | 
			
		||||
## 2025-03-03 - 1.4.0 - feat(core)
 | 
			
		||||
Introduced process management features using ProcessWrapper and enhanced configuration.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@
 | 
			
		||||
    "@push.rocks/npmextra": "^5.1.2",
 | 
			
		||||
    "@push.rocks/projectinfo": "^5.0.2",
 | 
			
		||||
    "@push.rocks/smartcli": "^4.0.11",
 | 
			
		||||
    "@push.rocks/smartdaemon": "^2.0.6",
 | 
			
		||||
    "@push.rocks/smartpath": "^5.0.18",
 | 
			
		||||
    "pidusage": "^4.0.0",
 | 
			
		||||
    "ps-tree": "^1.2.0"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										89
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										89
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							@@ -17,6 +17,9 @@ importers:
 | 
			
		||||
      '@push.rocks/smartcli':
 | 
			
		||||
        specifier: ^4.0.11
 | 
			
		||||
        version: 4.0.11
 | 
			
		||||
      '@push.rocks/smartdaemon':
 | 
			
		||||
        specifier: ^2.0.6
 | 
			
		||||
        version: 2.0.6
 | 
			
		||||
      '@push.rocks/smartpath':
 | 
			
		||||
        specifier: ^5.0.18
 | 
			
		||||
        version: 5.0.18
 | 
			
		||||
@@ -749,6 +752,9 @@ packages:
 | 
			
		||||
  '@push.rocks/smartcrypto@2.0.4':
 | 
			
		||||
    resolution: {integrity: sha512-1+/5bsjyataf5uUkUNnnVXGRAt+gHVk1KDzozjTqgqJxHvQk1d9fVDohL6CxUhUucTPtu5VR5xNBiV8YCDuGyw==}
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smartdaemon@2.0.6':
 | 
			
		||||
    resolution: {integrity: sha512-yFbZIT8Vb8fCdihM+kUnSluYmTzfARuZEs7Mbh+GjNJ9H+gbfyCt30BKocsPBUDkuliSAv/RlbYLILACNZlX8w==}
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smartdata@5.2.12':
 | 
			
		||||
    resolution: {integrity: sha512-vp0nz1P/SJcoFhyfZoewPbFSameWnuMuCkySvnb41TcCi1PFHA//KOYImdti/qURSOYwVoTKboDrnx1/ffHp7g==}
 | 
			
		||||
 | 
			
		||||
@@ -776,6 +782,9 @@ packages:
 | 
			
		||||
  '@push.rocks/smartfile@11.2.0':
 | 
			
		||||
    resolution: {integrity: sha512-0Gw6DvCQ2D/BXNN6airSC7hoSBut0p/uNWf2+rqO+D6VLhIJ/QUBvF6xm/LnpPI/zcF8YlDn/GEriInB5DUtEw==}
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smartfm@2.2.2':
 | 
			
		||||
    resolution: {integrity: sha512-kLrBv/vWXJmB558LI5C79fWXLKOnno998vnp3opfB+uyznT2E6LkcpKsxdjwe1V/r+Z5GlhXPOWmGgHPCzUR6w==}
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smartguard@3.1.0':
 | 
			
		||||
    resolution: {integrity: sha512-J23q84f1O+TwFGmd4lrO9XLHUh2DaLXo9PN/9VmTWYzTkQDv5JehmifXVI0esophXcCIfbdIu6hbt7/aHlDF4A==}
 | 
			
		||||
 | 
			
		||||
@@ -878,6 +887,9 @@ packages:
 | 
			
		||||
  '@push.rocks/smartstring@4.0.15':
 | 
			
		||||
    resolution: {integrity: sha512-NTNeOjWyg+aHtBTiQEyXamr7oTvYZ3wS1fudHo9ua7CLrykpK+i+RxFyJaLg1zB5x9xQF3NLEQecB14HPFX8Cg==}
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smartsystem@3.0.1':
 | 
			
		||||
    resolution: {integrity: sha512-+W9AiSJWcRAjthqDFT8rDli2+5k3bk8c9Psndy3uKN2YbaQkMZwWptZRI3WgpXMG9NhsjF8XrkyiH/xHv9AxzQ==}
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smarttime@4.1.1':
 | 
			
		||||
    resolution: {integrity: sha512-Ha/3J/G+zfTl4ahpZgF6oUOZnUjpLhrBja0OQ2cloFxF9sKT8I1COaSqIfBGDtoK2Nly4UD4aTJ3JcJNOg/kgA==}
 | 
			
		||||
 | 
			
		||||
@@ -978,6 +990,10 @@ packages:
 | 
			
		||||
    resolution: {integrity: sha512-FCRg5p5NFTyZnPsvy2sbheVGz67Zeno7VoZARrcP0O+hFtVPnQKnJ73ze11G+MKZ3dVCmYCh1Li+73R6Lx8XJA==}
 | 
			
		||||
    deprecated: This package has been deprecated in favour of the new package at @push.rocks/smartmime
 | 
			
		||||
 | 
			
		||||
  '@pushrocks/smartnetwork@3.0.2':
 | 
			
		||||
    resolution: {integrity: sha512-XKVeTzf22IRgAvY9m8naFlsjh5yYVCU4/Dqi7XnxQUVfrnrcNIJVo+9JIYjQetLbHiUOHAnthlZVP5yXppOxyw==}
 | 
			
		||||
    deprecated: This package has been deprecated in favour of the new package at @push.rocks/smartnetwork
 | 
			
		||||
 | 
			
		||||
  '@pushrocks/smartpath@4.0.3':
 | 
			
		||||
    resolution: {integrity: sha512-KWz4DWOrB0sPfk6L4i+CPOo+UK5HXNaLI7ZAaqJe1nEWoDrpyeds1dNDaqVAmSgX4riLGxVpslKH5MnABCPsPg==}
 | 
			
		||||
    deprecated: This package has been deprecated in favour of the new package at @push.rocks/smartpath
 | 
			
		||||
@@ -2252,6 +2268,10 @@ packages:
 | 
			
		||||
    resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==}
 | 
			
		||||
    engines: {node: '>= 0.10.0'}
 | 
			
		||||
 | 
			
		||||
  extend-shallow@2.0.1:
 | 
			
		||||
    resolution: {integrity: sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=}
 | 
			
		||||
    engines: {node: '>=0.10.0'}
 | 
			
		||||
 | 
			
		||||
  extend@3.0.2:
 | 
			
		||||
    resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
 | 
			
		||||
 | 
			
		||||
@@ -2478,6 +2498,10 @@ packages:
 | 
			
		||||
  graceful-fs@4.2.11:
 | 
			
		||||
    resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
 | 
			
		||||
 | 
			
		||||
  gray-matter@4.0.3:
 | 
			
		||||
    resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
 | 
			
		||||
    engines: {node: '>=6.0'}
 | 
			
		||||
 | 
			
		||||
  gunzip-maybe@1.4.2:
 | 
			
		||||
    resolution: {integrity: sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==}
 | 
			
		||||
    hasBin: true
 | 
			
		||||
@@ -2647,6 +2671,10 @@ packages:
 | 
			
		||||
    engines: {node: '>=8'}
 | 
			
		||||
    hasBin: true
 | 
			
		||||
 | 
			
		||||
  is-extendable@0.1.1:
 | 
			
		||||
    resolution: {integrity: sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=}
 | 
			
		||||
    engines: {node: '>=0.10.0'}
 | 
			
		||||
 | 
			
		||||
  is-extglob@2.1.1:
 | 
			
		||||
    resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=}
 | 
			
		||||
    engines: {node: '>=0.10.0'}
 | 
			
		||||
@@ -3727,6 +3755,10 @@ packages:
 | 
			
		||||
  sax@1.4.1:
 | 
			
		||||
    resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
 | 
			
		||||
 | 
			
		||||
  section-matter@1.0.0:
 | 
			
		||||
    resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
 | 
			
		||||
    engines: {node: '>=4'}
 | 
			
		||||
 | 
			
		||||
  semver@6.3.1:
 | 
			
		||||
    resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
 | 
			
		||||
    hasBin: true
 | 
			
		||||
@@ -3903,6 +3935,10 @@ packages:
 | 
			
		||||
    resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
 | 
			
		||||
    engines: {node: '>=12'}
 | 
			
		||||
 | 
			
		||||
  strip-bom-string@1.0.0:
 | 
			
		||||
    resolution: {integrity: sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=}
 | 
			
		||||
    engines: {node: '>=0.10.0'}
 | 
			
		||||
 | 
			
		||||
  strip-final-newline@2.0.0:
 | 
			
		||||
    resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
 | 
			
		||||
    engines: {node: '>=6'}
 | 
			
		||||
@@ -5527,6 +5563,17 @@ snapshots:
 | 
			
		||||
      '@types/node-forge': 1.3.11
 | 
			
		||||
      node-forge: 1.3.1
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smartdaemon@2.0.6':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@push.rocks/lik': 6.1.0
 | 
			
		||||
      '@push.rocks/smartfile': 11.2.0
 | 
			
		||||
      '@push.rocks/smartfm': 2.2.2
 | 
			
		||||
      '@push.rocks/smartlog': 3.0.7
 | 
			
		||||
      '@push.rocks/smartlog-destination-local': 9.0.2
 | 
			
		||||
      '@push.rocks/smartpath': 5.0.18
 | 
			
		||||
      '@push.rocks/smartshell': 3.2.3
 | 
			
		||||
      '@push.rocks/smartsystem': 3.0.1
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smartdata@5.2.12(@aws-sdk/credential-providers@3.758.0)(socks@2.8.4)':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@push.rocks/lik': 6.1.0
 | 
			
		||||
@@ -5619,6 +5666,10 @@ snapshots:
 | 
			
		||||
      glob: 11.0.1
 | 
			
		||||
      js-yaml: 4.1.0
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smartfm@2.2.2':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      gray-matter: 4.0.3
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smartguard@3.1.0':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@push.rocks/smartpromise': 4.2.3
 | 
			
		||||
@@ -5911,6 +5962,14 @@ snapshots:
 | 
			
		||||
      strip-indent: 4.0.0
 | 
			
		||||
      url: 0.11.4
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smartsystem@3.0.1':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@pushrocks/lik': 6.0.2
 | 
			
		||||
      '@pushrocks/smartenv': 5.0.5
 | 
			
		||||
      '@pushrocks/smartnetwork': 3.0.2
 | 
			
		||||
      '@pushrocks/smartpromise': 3.1.10
 | 
			
		||||
      systeminformation: 5.25.11
 | 
			
		||||
 | 
			
		||||
  '@push.rocks/smarttime@4.1.1':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@push.rocks/lik': 6.1.0
 | 
			
		||||
@@ -6119,6 +6178,16 @@ snapshots:
 | 
			
		||||
      '@types/mime-types': 2.1.4
 | 
			
		||||
      mime-types: 2.1.35
 | 
			
		||||
 | 
			
		||||
  '@pushrocks/smartnetwork@3.0.2':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@pushrocks/smartping': 1.0.8
 | 
			
		||||
      '@pushrocks/smartpromise': 3.1.10
 | 
			
		||||
      '@pushrocks/smartstring': 4.0.7
 | 
			
		||||
      '@types/default-gateway': 3.0.1
 | 
			
		||||
      isopen: 1.3.0
 | 
			
		||||
      public-ip: 6.0.2
 | 
			
		||||
      systeminformation: 5.25.11
 | 
			
		||||
 | 
			
		||||
  '@pushrocks/smartpath@4.0.3': {}
 | 
			
		||||
 | 
			
		||||
  '@pushrocks/smartpath@5.0.5': {}
 | 
			
		||||
@@ -7663,6 +7732,10 @@ snapshots:
 | 
			
		||||
    transitivePeerDependencies:
 | 
			
		||||
      - supports-color
 | 
			
		||||
 | 
			
		||||
  extend-shallow@2.0.1:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      is-extendable: 0.1.1
 | 
			
		||||
 | 
			
		||||
  extend@3.0.2: {}
 | 
			
		||||
 | 
			
		||||
  extract-zip@2.0.1:
 | 
			
		||||
@@ -7935,6 +8008,13 @@ snapshots:
 | 
			
		||||
 | 
			
		||||
  graceful-fs@4.2.11: {}
 | 
			
		||||
 | 
			
		||||
  gray-matter@4.0.3:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      js-yaml: 3.14.1
 | 
			
		||||
      kind-of: 6.0.3
 | 
			
		||||
      section-matter: 1.0.0
 | 
			
		||||
      strip-bom-string: 1.0.0
 | 
			
		||||
 | 
			
		||||
  gunzip-maybe@1.4.2:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      browserify-zlib: 0.1.4
 | 
			
		||||
@@ -8126,6 +8206,8 @@ snapshots:
 | 
			
		||||
 | 
			
		||||
  is-docker@2.2.1: {}
 | 
			
		||||
 | 
			
		||||
  is-extendable@0.1.1: {}
 | 
			
		||||
 | 
			
		||||
  is-extglob@2.1.1: {}
 | 
			
		||||
 | 
			
		||||
  is-fullwidth-code-point@3.0.0: {}
 | 
			
		||||
@@ -9436,6 +9518,11 @@ snapshots:
 | 
			
		||||
 | 
			
		||||
  sax@1.4.1: {}
 | 
			
		||||
 | 
			
		||||
  section-matter@1.0.0:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      extend-shallow: 2.0.1
 | 
			
		||||
      kind-of: 6.0.3
 | 
			
		||||
 | 
			
		||||
  semver@6.3.1: {}
 | 
			
		||||
 | 
			
		||||
  semver@7.7.1: {}
 | 
			
		||||
@@ -9671,6 +9758,8 @@ snapshots:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      ansi-regex: 6.1.0
 | 
			
		||||
 | 
			
		||||
  strip-bom-string@1.0.0: {}
 | 
			
		||||
 | 
			
		||||
  strip-final-newline@2.0.0: {}
 | 
			
		||||
 | 
			
		||||
  strip-indent@4.0.0:
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,6 @@
 | 
			
		||||
 */
 | 
			
		||||
export const commitinfo = {
 | 
			
		||||
  name: '@git.zone/tspm',
 | 
			
		||||
  version: '1.4.0',
 | 
			
		||||
  version: '1.5.0',
 | 
			
		||||
  description: 'a no fuzz process manager'
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import * as plugins from './plugins.js';
 | 
			
		||||
import { ProcessWrapper } from './classes.processwrapper.js';
 | 
			
		||||
import { ProcessWrapper, type IProcessLog } from './classes.processwrapper.js';
 | 
			
		||||
 | 
			
		||||
export interface IMonitorConfig {
 | 
			
		||||
  name?: string;                 // Optional name to identify the instance
 | 
			
		||||
@@ -161,7 +161,7 @@ export class ProcessMonitor {
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the current logs from the process
 | 
			
		||||
   */
 | 
			
		||||
  public getLogs(limit?: number): Array<{ timestamp: Date, type: string, message: string }> {
 | 
			
		||||
  public getLogs(limit?: number): IProcessLog[] {
 | 
			
		||||
    if (!this.processWrapper) {
 | 
			
		||||
      return [];
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										287
									
								
								ts/cli.ts
									
									
									
									
									
								
							
							
						
						
									
										287
									
								
								ts/cli.ts
									
									
									
									
									
								
							@@ -1,29 +1,300 @@
 | 
			
		||||
import * as plugins from './plugins.js';
 | 
			
		||||
import * as paths from './paths.js';
 | 
			
		||||
import { Tspm, IProcessConfig } from './classes.tspm.js';
 | 
			
		||||
 | 
			
		||||
export const run = async () => {
 | 
			
		||||
  const tspmProjectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir);
 | 
			
		||||
  const tspm = new Tspm();
 | 
			
		||||
 | 
			
		||||
  const smartcliInstance = new plugins.smartcli.Smartcli();
 | 
			
		||||
  smartcliInstance.addVersion(tspmProjectinfo.npm.version);
 | 
			
		||||
  
 | 
			
		||||
  // Default command - show help and list processes
 | 
			
		||||
  smartcliInstance.standardCommand().subscribe({
 | 
			
		||||
    next: (argvArg) => {
 | 
			
		||||
      console.log(`Please specify a command.`)
 | 
			
		||||
    next: async (argvArg) => {
 | 
			
		||||
      console.log(`TSPM - TypeScript Process Manager v${tspmProjectinfo.npm.version}`);
 | 
			
		||||
      console.log('Usage: tspm [command] [options]');
 | 
			
		||||
      console.log('\nCommands:');
 | 
			
		||||
      console.log('  start <script>           Start a process');
 | 
			
		||||
      console.log('  startAsDaemon <script>   Start a process in daemon mode');
 | 
			
		||||
      console.log('  list                     List all processes');
 | 
			
		||||
      console.log('  stop <id>                Stop a process');
 | 
			
		||||
      console.log('  restart <id>             Restart a process');
 | 
			
		||||
      console.log('  delete <id>              Delete a process');
 | 
			
		||||
      console.log('  describe <id>            Show details for a process');
 | 
			
		||||
      console.log('\nUse tspm [command] --help for more information about a command.');
 | 
			
		||||
      
 | 
			
		||||
      // Show current process list
 | 
			
		||||
      console.log('\nProcess List:');
 | 
			
		||||
      const processes = tspm.list();
 | 
			
		||||
      
 | 
			
		||||
      if (processes.length === 0) {
 | 
			
		||||
        console.log('  No processes running. Use "tspm start" to start a process.');
 | 
			
		||||
      } else {
 | 
			
		||||
        console.log('┌─────────┬─────────────┬───────────┬───────────┬──────────┐');
 | 
			
		||||
        console.log('│ ID      │ Name        │ Status    │ Memory    │ Restarts │');
 | 
			
		||||
        console.log('├─────────┼─────────────┼───────────┼───────────┼──────────┤');
 | 
			
		||||
        
 | 
			
		||||
        for (const proc of processes) {
 | 
			
		||||
          console.log(`│ ${pad(proc.id, 8)} │ ${pad(proc.id, 12)} │ ${pad(proc.status, 10)} │ ${pad(formatMemory(proc.memory), 10)} │ ${pad(String(proc.restarts), 9)} │`);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        console.log('└─────────┴─────────────┴───────────┴───────────┴──────────┘');
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  smartcliInstance.addCommand('restart').subscribe({
 | 
			
		||||
 | 
			
		||||
  })
 | 
			
		||||
  // Start command - start a new process
 | 
			
		||||
  smartcliInstance.addCommand('start').subscribe({
 | 
			
		||||
    next: async (argvArg) => {
 | 
			
		||||
      const script = argvArg._.length > 1 ? String(argvArg._[1]) : '';
 | 
			
		||||
      if (!script) {
 | 
			
		||||
        console.error('Error: Missing script argument. Usage: tspm start <script>');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // Parse additional options
 | 
			
		||||
      const name = argvArg.name || script;
 | 
			
		||||
      const cwd = argvArg.cwd || process.cwd();
 | 
			
		||||
      const memLimit = parseMemoryString(argvArg.memory || '500MB');
 | 
			
		||||
      
 | 
			
		||||
      try {
 | 
			
		||||
        const processConfig: IProcessConfig = {
 | 
			
		||||
          id: argvArg.id || name.replace(/[^a-zA-Z0-9_-]/g, '_').toLowerCase(),
 | 
			
		||||
          name: name,
 | 
			
		||||
          projectDir: cwd,
 | 
			
		||||
          command: script,
 | 
			
		||||
          args: argvArg.args ? String(argvArg.args).split(' ') : undefined,
 | 
			
		||||
          memoryLimitBytes: memLimit,
 | 
			
		||||
          monitorIntervalMs: Number(argvArg.interval) || 5000,
 | 
			
		||||
          autorestart: argvArg.autorestart !== 'false',
 | 
			
		||||
          watch: Boolean(argvArg.watch)
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        await tspm.start(processConfig);
 | 
			
		||||
        console.log(`Process ${processConfig.id} started successfully.`);
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.error(`Error starting process: ${error.message}`);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Start as daemon command
 | 
			
		||||
  smartcliInstance.addCommand('startAsDaemon').subscribe({
 | 
			
		||||
    next: async (argvArg) => {
 | 
			
		||||
      const script = argvArg._.length > 1 ? String(argvArg._[1]) : '';
 | 
			
		||||
      if (!script) {
 | 
			
		||||
        console.error('Error: Missing script argument. Usage: tspm startAsDaemon <script>');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // For daemon mode, we'll detach from the console
 | 
			
		||||
      const daemonProcess = plugins.childProcess.spawn(
 | 
			
		||||
        process.execPath,
 | 
			
		||||
        [
 | 
			
		||||
          ...process.execArgv,
 | 
			
		||||
          process.argv[1], // The tspm script path
 | 
			
		||||
          'start',
 | 
			
		||||
          script,
 | 
			
		||||
          ...process.argv.slice(3) // Pass other arguments
 | 
			
		||||
        ],
 | 
			
		||||
        {
 | 
			
		||||
          detached: true,
 | 
			
		||||
          stdio: 'ignore',
 | 
			
		||||
          cwd: process.cwd()
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      // Unref to allow parent to exit
 | 
			
		||||
      daemonProcess.unref();
 | 
			
		||||
      
 | 
			
		||||
      console.log(`Started process ${script} as daemon.`);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  // Stop command
 | 
			
		||||
  smartcliInstance.addCommand('stop').subscribe({
 | 
			
		||||
    next: async (argvArg) => {
 | 
			
		||||
      const id = argvArg._.length > 1 ? String(argvArg._[1]) : '';
 | 
			
		||||
      
 | 
			
		||||
      if (!id) {
 | 
			
		||||
        console.error('Error: Missing process ID. Usage: tspm stop <id>');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      try {
 | 
			
		||||
        await tspm.stop(id);
 | 
			
		||||
        console.log(`Process ${id} stopped.`);
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.error(`Error stopping process: ${error.message}`);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  })
 | 
			
		||||
  // Restart command
 | 
			
		||||
  smartcliInstance.addCommand('restart').subscribe({
 | 
			
		||||
    next: async (argvArg) => {
 | 
			
		||||
      const id = argvArg._.length > 1 ? String(argvArg._[1]) : '';
 | 
			
		||||
      
 | 
			
		||||
      if (!id) {
 | 
			
		||||
        console.error('Error: Missing process ID. Usage: tspm restart <id>');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      try {
 | 
			
		||||
        await tspm.restart(id);
 | 
			
		||||
        console.log(`Process ${id} restarted.`);
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.error(`Error restarting process: ${error.message}`);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Delete command
 | 
			
		||||
  smartcliInstance.addCommand('delete').subscribe({
 | 
			
		||||
    next: async (argvArg) => {
 | 
			
		||||
      const id = argvArg._.length > 1 ? String(argvArg._[1]) : '';
 | 
			
		||||
      
 | 
			
		||||
      if (!id) {
 | 
			
		||||
        console.error('Error: Missing process ID. Usage: tspm delete <id>');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      try {
 | 
			
		||||
        await tspm.delete(id);
 | 
			
		||||
        console.log(`Process ${id} deleted.`);
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.error(`Error deleting process: ${error.message}`);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // List command
 | 
			
		||||
  smartcliInstance.addCommand('list').subscribe({
 | 
			
		||||
    next: async (argvArg) => {
 | 
			
		||||
      const processes = tspm.list();
 | 
			
		||||
      
 | 
			
		||||
      if (processes.length === 0) {
 | 
			
		||||
        console.log('No processes running.');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      console.log('┌─────────┬─────────────┬───────────┬───────────┬──────────┐');
 | 
			
		||||
      console.log('│ ID      │ Name        │ Status    │ Memory    │ Restarts │');
 | 
			
		||||
      console.log('├─────────┼─────────────┼───────────┼───────────┼──────────┤');
 | 
			
		||||
      
 | 
			
		||||
      for (const proc of processes) {
 | 
			
		||||
        console.log(`│ ${pad(proc.id, 8)} │ ${pad(proc.id, 12)} │ ${pad(proc.status, 10)} │ ${pad(formatMemory(proc.memory), 10)} │ ${pad(String(proc.restarts), 9)} │`);
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      console.log('└─────────┴─────────────┴───────────┴───────────┴──────────┘');
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Describe command
 | 
			
		||||
  smartcliInstance.addCommand('describe').subscribe({
 | 
			
		||||
    next: async (argvArg) => {
 | 
			
		||||
      const id = argvArg._.length > 1 ? String(argvArg._[1]) : '';
 | 
			
		||||
      
 | 
			
		||||
      if (!id) {
 | 
			
		||||
        console.error('Error: Missing process ID. Usage: tspm describe <id>');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      const details = tspm.describe(id);
 | 
			
		||||
      
 | 
			
		||||
      if (!details) {
 | 
			
		||||
        console.error(`Process with ID '${id}' not found.`);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      console.log(`Details for process '${id}':`);
 | 
			
		||||
      console.log(`  Status: ${details.info.status}`);
 | 
			
		||||
      console.log(`  Memory: ${formatMemory(details.info.memory)}`);
 | 
			
		||||
      console.log(`  Restarts: ${details.info.restarts}`);
 | 
			
		||||
      console.log(`  Command: ${details.config.command}`);
 | 
			
		||||
      console.log(`  Directory: ${details.config.projectDir}`);
 | 
			
		||||
      console.log(`  Memory limit: ${formatMemory(details.config.memoryLimitBytes)}`);
 | 
			
		||||
      
 | 
			
		||||
      if (details.config.args && details.config.args.length > 0) {
 | 
			
		||||
        console.log(`  Arguments: ${details.config.args.join(' ')}`);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  
 | 
			
		||||
  // Logs command
 | 
			
		||||
  smartcliInstance.addCommand('logs').subscribe({
 | 
			
		||||
    next: async (argvArg) => {
 | 
			
		||||
      const id = argvArg._.length > 1 ? String(argvArg._[1]) : '';
 | 
			
		||||
      
 | 
			
		||||
      if (!id) {
 | 
			
		||||
        console.error('Error: Missing process ID. Usage: tspm logs <id>');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      const lines = Number(argvArg.lines || argvArg.n) || 20;
 | 
			
		||||
      const logs = tspm.getLogs(id, lines);
 | 
			
		||||
      
 | 
			
		||||
      if (logs.length === 0) {
 | 
			
		||||
        console.log(`No logs found for process '${id}'.`);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // Display logs with colors for different log types
 | 
			
		||||
      for (const log of logs) {
 | 
			
		||||
        const timestamp = log.timestamp.toISOString();
 | 
			
		||||
        const prefix = `[${timestamp}] `;
 | 
			
		||||
        
 | 
			
		||||
        switch (log.type) {
 | 
			
		||||
          case 'stdout':
 | 
			
		||||
            console.log(`${prefix}${log.message}`);
 | 
			
		||||
            break;
 | 
			
		||||
          case 'stderr':
 | 
			
		||||
            console.error(`${prefix}${log.message}`);
 | 
			
		||||
            break;
 | 
			
		||||
          case 'system':
 | 
			
		||||
            console.log(`${prefix}[SYSTEM] ${log.message}`);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Start parsing
 | 
			
		||||
  smartcliInstance.startParse();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Helper function to format memory usage
 | 
			
		||||
function formatMemory(bytes: number): string {
 | 
			
		||||
  if (bytes === 0) return '0 B';
 | 
			
		||||
  const k = 1024;
 | 
			
		||||
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
 | 
			
		||||
  const i = Math.floor(Math.log(bytes) / Math.log(k));
 | 
			
		||||
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper function to parse memory strings like "500MB"
 | 
			
		||||
function parseMemoryString(memString: string): number {
 | 
			
		||||
  const units = {
 | 
			
		||||
    'B': 1,
 | 
			
		||||
    'KB': 1024,
 | 
			
		||||
    'MB': 1024 * 1024,
 | 
			
		||||
    'GB': 1024 * 1024 * 1024,
 | 
			
		||||
    'TB': 1024 * 1024 * 1024 * 1024
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  const match = memString.match(/^(\d+(?:\.\d+)?)\s*([KMGT]?B)$/i);
 | 
			
		||||
  if (!match) {
 | 
			
		||||
    throw new Error(`Invalid memory format: ${memString}. Use format like 500MB`);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  const value = parseFloat(match[1]);
 | 
			
		||||
  const unit = match[2].toUpperCase();
 | 
			
		||||
  
 | 
			
		||||
  return value * units[unit];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper function to pad strings for table display
 | 
			
		||||
function pad(str: string, length: number): string {
 | 
			
		||||
  return str.padEnd(length);
 | 
			
		||||
}
 | 
			
		||||
@@ -10,14 +10,16 @@ export {
 | 
			
		||||
// @push.rocks scope
 | 
			
		||||
import * as npmextra from '@push.rocks/npmextra';
 | 
			
		||||
import * as projectinfo from '@push.rocks/projectinfo';
 | 
			
		||||
import * as smartpath from '@push.rocks/smartpath';
 | 
			
		||||
import * as smartcli from '@push.rocks/smartcli';
 | 
			
		||||
import * as smartdaemon from '@push.rocks/smartdaemon';
 | 
			
		||||
import * as smartpath from '@push.rocks/smartpath';
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
  npmextra,
 | 
			
		||||
  projectinfo,
 | 
			
		||||
  smartpath,
 | 
			
		||||
  smartcli,
 | 
			
		||||
  smartdaemon,
 | 
			
		||||
  smartpath,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// third-party scope
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user