feat(cli): Enhance CLI with new process management commands
This commit is contained in:
parent
0232741b89
commit
2dc766fa6e
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user