fix(cli): improve project metadata loading and normalize CLI error handling
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-05-09 - 5.10.5 - fix(cli)
|
||||||
|
improve project metadata loading and normalize CLI error handling
|
||||||
|
|
||||||
|
- load package metadata asynchronously via ProjectInfo.create in the CLI and daemon to avoid initialization issues
|
||||||
|
- use handleError when reporting daemon and service command failures for safer error messages
|
||||||
|
- tighten interactive edit validation for required text fields and refresh documentation to match current CLI behavior
|
||||||
|
|
||||||
## 2026-03-24 - 5.10.4 - fix(crash-logging)
|
## 2026-03-24 - 5.10.4 - fix(crash-logging)
|
||||||
migrate filesystem persistence to smartfs and stabilize crash log tests
|
migrate filesystem persistence to smartfs and stabilize crash log tests
|
||||||
|
|
||||||
|
|||||||
+10
-12
@@ -24,19 +24,18 @@
|
|||||||
"tspm": "./cli.js"
|
"tspm": "./cli.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^4.3.0",
|
"@git.zone/tsbuild": "^4.4.0",
|
||||||
"@git.zone/tsbundle": "^2.9.3",
|
"@git.zone/tsbundle": "^2.10.1",
|
||||||
"@git.zone/tsrun": "^2.0.1",
|
"@git.zone/tsrun": "^2.0.3",
|
||||||
"@git.zone/tstest": "^3.5.1",
|
"@git.zone/tstest": "^3.6.5",
|
||||||
"@push.rocks/tapbundle": "^6.0.3",
|
"@types/node": "^25.6.2"
|
||||||
"@types/node": "^25.5.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@push.rocks/projectinfo": "^5.0.2",
|
"@push.rocks/projectinfo": "^5.1.0",
|
||||||
"@push.rocks/smartcli": "^4.0.20",
|
"@push.rocks/smartcli": "^4.0.21",
|
||||||
"@push.rocks/smartconfig": "^6.0.1",
|
"@push.rocks/smartconfig": "^6.1.1",
|
||||||
"@push.rocks/smartdaemon": "^2.1.0",
|
"@push.rocks/smartdaemon": "^2.1.1",
|
||||||
"@push.rocks/smartfs": "^1.5.0",
|
"@push.rocks/smartfs": "^1.5.1",
|
||||||
"@push.rocks/smartinteract": "^2.0.16",
|
"@push.rocks/smartinteract": "^2.0.16",
|
||||||
"@push.rocks/smartipc": "^2.3.0",
|
"@push.rocks/smartipc": "^2.3.0",
|
||||||
"@push.rocks/smartpath": "^6.0.0",
|
"@push.rocks/smartpath": "^6.0.0",
|
||||||
@@ -67,7 +66,6 @@
|
|||||||
"readme.md"
|
"readme.md"
|
||||||
],
|
],
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"overrides": {},
|
|
||||||
"onlyBuiltDependencies": [
|
"onlyBuiltDependencies": [
|
||||||
"esbuild",
|
"esbuild",
|
||||||
"mongodb-memory-server",
|
"mongodb-memory-server",
|
||||||
|
|||||||
Generated
+3242
-5143
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@ TSPM is your production-ready process manager that handles the hard parts of run
|
|||||||
- 🧠 **Smart Memory Management** — Tracks memory across entire process trees (parent + children), enforces limits, and auto-restarts on OOM
|
- 🧠 **Smart Memory Management** — Tracks memory across entire process trees (parent + children), enforces limits, and auto-restarts on OOM
|
||||||
- 💾 **Persistent Log Storage** — 10MB in-memory ring buffer per process, auto-persists to disk on stop/restart/crash
|
- 💾 **Persistent Log Storage** — 10MB in-memory ring buffer per process, auto-persists to disk on stop/restart/crash
|
||||||
- 🔄 **Intelligent Auto-Restart** — Crashed processes restart with incremental backoff (1s → 10s), auto-stop after 10 consecutive failures
|
- 🔄 **Intelligent Auto-Restart** — Crashed processes restart with incremental backoff (1s → 10s), auto-stop after 10 consecutive failures
|
||||||
- 👀 **File Watching** — Auto-restart on file changes for seamless development workflows
|
- 🧾 **Persistent Process Configs** — Saved process definitions and desired states survive daemon restarts
|
||||||
- 🌳 **Process Tree Tracking** — Monitors parent and all child processes as a unit — no orphans, ever
|
- 🌳 **Process Tree Tracking** — Monitors parent and all child processes as a unit — no orphans, ever
|
||||||
- 🏗️ **Daemon Architecture** — Persistent background service that survives terminal sessions via Unix socket IPC
|
- 🏗️ **Daemon Architecture** — Persistent background service that survives terminal sessions via Unix socket IPC
|
||||||
- 📊 **Beautiful CLI** — Clean, informative output with table views, real-time log streaming, and search
|
- 📊 **Beautiful CLI** — Clean, informative output with table views, real-time log streaming, and search
|
||||||
@@ -83,8 +83,8 @@ Register a new process configuration (without starting it).
|
|||||||
| `--name <name>` | Process name | command string |
|
| `--name <name>` | Process name | command string |
|
||||||
| `--memory <size>` | Memory limit (e.g. `512MB`, `2GB`) | `512MB` |
|
| `--memory <size>` | Memory limit (e.g. `512MB`, `2GB`) | `512MB` |
|
||||||
| `--cwd <path>` | Working directory | current directory |
|
| `--cwd <path>` | Working directory | current directory |
|
||||||
| `--watch` | Enable file watching | `false` |
|
| `--watch` | Store watch intent in the process config | `false` |
|
||||||
| `--watch-paths <paths>` | Comma-separated watch paths | — |
|
| `--watch-paths <paths>` | Comma-separated watch paths stored with the config | — |
|
||||||
| `--autorestart` | Auto-restart on crash | `true` |
|
| `--autorestart` | Auto-restart on crash | `true` |
|
||||||
| `-i, --interactive` | Enter interactive edit after adding | — |
|
| `-i, --interactive` | Enter interactive edit after adding | — |
|
||||||
|
|
||||||
@@ -95,8 +95,8 @@ tspm add "node server.js" --name api-server
|
|||||||
# TypeScript with 2GB memory limit
|
# TypeScript with 2GB memory limit
|
||||||
tspm add "tsx src/index.ts" --name production-api --memory 2GB
|
tspm add "tsx src/index.ts" --name production-api --memory 2GB
|
||||||
|
|
||||||
# Dev mode with file watching
|
# TypeScript entry file (runs through tsx automatically)
|
||||||
tspm add "tsx watch src/index.ts" --name dev-server --watch --watch-paths "src,config"
|
tspm add ./src/index.ts --name ts-worker --memory 2GB
|
||||||
|
|
||||||
# One-shot worker (no auto-restart)
|
# One-shot worker (no auto-restart)
|
||||||
tspm add "node worker.js" --name batch-job --autorestart false
|
tspm add "node worker.js" --name batch-job --autorestart false
|
||||||
@@ -131,12 +131,13 @@ Stop and restart a process, preserving its configuration.
|
|||||||
tspm restart name:my-server
|
tspm restart name:my-server
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `tspm delete <target>`
|
#### `tspm delete <target>` / `tspm remove <target>`
|
||||||
|
|
||||||
Stop, remove from management, and delete persisted logs.
|
Stop, remove from management, and delete persisted logs.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
tspm delete name:old-server
|
tspm delete name:old-server
|
||||||
|
tspm remove id:3
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `tspm edit <target>`
|
#### `tspm edit <target>`
|
||||||
@@ -161,16 +162,16 @@ tspm search api
|
|||||||
|
|
||||||
#### `tspm list`
|
#### `tspm list`
|
||||||
|
|
||||||
Display all managed processes in a table.
|
Display all managed processes with live runtime stats. Use `tspm describe <target>` for saved command, directory, and full process configuration details.
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────┬─────────────┬──────────┬───────┬──────────┬──────────┐
|
┌─────────┬─────────────┬───────────┬───────────┬──────────┬──────────┬─────────┐
|
||||||
│ ID │ Name │ Status │ PID │ Memory │ Restarts │
|
│ ID │ Name │ Status │ PID │ Memory │ CPU │ Restarts │
|
||||||
├─────┼─────────────┼──────────┼───────┼──────────┼──────────┤
|
├─────────┼─────────────┼───────────┼───────────┼──────────┼──────────┼──────────┤
|
||||||
│ 1 │ my-app │ online │ 45123 │ 245.3 MB │ 0 │
|
│ 1 │ 1 │ online │ 45123 │ 245.3 MB │ 2.1% │ 0 │
|
||||||
│ 2 │ worker │ online │ 45456 │ 128.7 MB │ 2 │
|
│ 2 │ 2 │ online │ 45456 │ 128.7 MB │ 0.5% │ 2 │
|
||||||
│ 3 │ api-server │ stopped │ - │ 0 B │ 5 │
|
│ 3 │ 3 │ stopped │ - │ 0 B │ - │ 5 │
|
||||||
└─────┴─────────────┴──────────┴───────┴──────────┴──────────┘
|
└─────────┴─────────────┴───────────┴───────────┴──────────┴──────────┴──────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `tspm describe <target>`
|
#### `tspm describe <target>`
|
||||||
@@ -194,7 +195,6 @@ tspm describe name:my-server
|
|||||||
# Directory: /home/user/project
|
# Directory: /home/user/project
|
||||||
# Memory Limit: 2 GB
|
# Memory Limit: 2 GB
|
||||||
# Auto-restart: true
|
# Auto-restart: true
|
||||||
# Watch: disabled
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `tspm logs <target> [options]`
|
#### `tspm logs <target> [options]`
|
||||||
@@ -230,18 +230,20 @@ tspm logs name:my-server --since 10m --ndjson
|
|||||||
tspm start-all # Start all saved processes
|
tspm start-all # Start all saved processes
|
||||||
tspm stop-all # Stop all running processes
|
tspm stop-all # Stop all running processes
|
||||||
tspm restart-all # Restart all running processes
|
tspm restart-all # Restart all running processes
|
||||||
|
tspm restart all # Alternate all-process restart form
|
||||||
tspm reset # ⚠️ Stop all + clear all configs (prompts for confirmation)
|
tspm reset # ⚠️ Stop all + clear all configs (prompts for confirmation)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Daemon Management
|
### Daemon Management
|
||||||
|
|
||||||
The daemon is a persistent background service that manages all processes. It starts automatically when needed.
|
The daemon is a persistent background service that manages all processes. Start it explicitly for the current session, or install it as a systemd service for boot startup.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
tspm daemon start # Start the daemon
|
tspm daemon start # Start the daemon
|
||||||
tspm daemon stop # Stop daemon + all managed processes
|
tspm daemon stop # Stop daemon + all managed processes
|
||||||
tspm daemon restart # Restart daemon (preserves processes)
|
tspm daemon restart # Restart daemon (preserves processes)
|
||||||
tspm daemon status # Check daemon health + stats
|
tspm daemon status # Check daemon health + stats
|
||||||
|
tspm stats # Detailed daemon stats + process table
|
||||||
```
|
```
|
||||||
|
|
||||||
### System Service (systemd)
|
### System Service (systemd)
|
||||||
@@ -285,7 +287,7 @@ TSPM uses a clean three-tier architecture:
|
|||||||
│ │ - Memory tracking & limits │ │
|
│ │ - Memory tracking & limits │ │
|
||||||
│ │ - Auto-restart logic │ │
|
│ │ - Auto-restart logic │ │
|
||||||
│ │ - Log persistence (10MB) │ │
|
│ │ - Log persistence (10MB) │ │
|
||||||
│ │ - File watching │ │
|
│ │ - Desired state restoration │ │
|
||||||
│ └────────────┬─────────────────────┘ │
|
│ └────────────┬─────────────────────┘ │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ┌────────────▼─────────────────────┐ │
|
│ ┌────────────▼─────────────────────┐ │
|
||||||
@@ -310,7 +312,7 @@ TSPM uses a clean three-tier architecture:
|
|||||||
| **CLI** | Lightweight client that sends commands to daemon via IPC |
|
| **CLI** | Lightweight client that sends commands to daemon via IPC |
|
||||||
| **Daemon** | Persistent background service managing all processes |
|
| **Daemon** | Persistent background service managing all processes |
|
||||||
| **ProcessManager** | High-level orchestration, config persistence, state management |
|
| **ProcessManager** | High-level orchestration, config persistence, state management |
|
||||||
| **ProcessMonitor** | Memory limits, auto-restart with backoff, log persistence, file watching |
|
| **ProcessMonitor** | Memory limits, auto-restart with backoff, log persistence, process-tree stats |
|
||||||
| **ProcessWrapper** | Low-level process lifecycle, stream handling, signal management |
|
| **ProcessWrapper** | Low-level process lifecycle, stream handling, signal management |
|
||||||
| **CrashLogManager** | Detailed crash reports with metadata and log history |
|
| **CrashLogManager** | Detailed crash reports with metadata and log history |
|
||||||
|
|
||||||
@@ -399,14 +401,9 @@ Multi-stage shutdown for reliability:
|
|||||||
3. Send **SIGKILL** if still alive
|
3. Send **SIGKILL** if still alive
|
||||||
4. Clean up **all child processes** in the tree
|
4. Clean up **all child processes** in the tree
|
||||||
|
|
||||||
### File Watching
|
### TypeScript Entry Files
|
||||||
|
|
||||||
Development-friendly auto-restart:
|
If `tspm add` receives a single `.ts` file, TSPM resolves it through `tsx` automatically and stores the resolved command plus file argument in the process config. Full command strings are still executed through the shell, so existing `node`, `tsx`, `pnpm`, or custom commands work as expected.
|
||||||
|
|
||||||
- Watch specific directories or files
|
|
||||||
- `node_modules` ignored by default
|
|
||||||
- Debounced restart on file changes
|
|
||||||
- Configurable via `--watch-paths`
|
|
||||||
|
|
||||||
## 🐛 Debugging
|
## 🐛 Debugging
|
||||||
|
|
||||||
@@ -417,8 +414,11 @@ tspm daemon status
|
|||||||
# View process logs
|
# View process logs
|
||||||
tspm logs name:my-app --lines 200
|
tspm logs name:my-app --lines 200
|
||||||
|
|
||||||
# Check daemon stderr
|
# Start with verbose daemon diagnostics
|
||||||
tail -f /tmp/daemon-stderr.log
|
TSPM_DEBUG=true tspm daemon start
|
||||||
|
|
||||||
|
# For systemd-managed daemon logs
|
||||||
|
journalctl -u smartdaemon_tspm-daemon -f
|
||||||
|
|
||||||
# Force daemon restart
|
# Force daemon restart
|
||||||
tspm daemon restart
|
tspm daemon restart
|
||||||
@@ -449,13 +449,13 @@ tspm daemon restart
|
|||||||
|
|
||||||
- 🚀 **Production Node.js apps** — Reliable process management with memory guards
|
- 🚀 **Production Node.js apps** — Reliable process management with memory guards
|
||||||
- 🔧 **Microservices** — Manage multiple services from a single tool
|
- 🔧 **Microservices** — Manage multiple services from a single tool
|
||||||
- 👨💻 **Development** — File watching and instant auto-restart
|
- 👨💻 **Development** — TypeScript entry files, local workers, and quick daemon lifecycle commands
|
||||||
- 🏭 **Workers & Jobs** — Queue workers, cron jobs, background tasks
|
- 🏭 **Workers & Jobs** — Queue workers, cron jobs, background tasks
|
||||||
- 📊 **Resource-constrained environments** — Memory limits prevent OOM kills
|
- 📊 **Resource-constrained environments** — Memory limits prevent OOM kills
|
||||||
|
|
||||||
## License and Legal Information
|
## License and Legal Information
|
||||||
|
|
||||||
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./license) file.
|
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file.
|
||||||
|
|
||||||
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@git.zone/tspm',
|
name: '@git.zone/tspm',
|
||||||
version: '5.10.4',
|
version: '5.10.5',
|
||||||
description: 'a no fuzz process manager'
|
description: 'a no fuzz process manager'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as plugins from '../../plugins.js';
|
import * as plugins from '../../plugins.js';
|
||||||
import * as paths from '../../../paths.js';
|
import * as paths from '../../../paths.js';
|
||||||
import { tspmIpcClient } from '../../../client/tspm.ipcclient.js';
|
import { tspmIpcClient } from '../../../client/tspm.ipcclient.js';
|
||||||
import { Logger } from '../../../shared/common/utils.errorhandler.js';
|
import { handleError, Logger } from '../../../shared/common/utils.errorhandler.js';
|
||||||
import type { CliArguments } from '../../types.js';
|
import type { CliArguments } from '../../types.js';
|
||||||
import { formatMemory } from '../../helpers/memory.js';
|
import { formatMemory } from '../../helpers/memory.js';
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ export function registerDaemonCommand(smartcli: plugins.smartcli.Smartcli) {
|
|||||||
// Disconnect from the daemon after starting
|
// Disconnect from the daemon after starting
|
||||||
await tspmIpcClient.disconnect();
|
await tspmIpcClient.disconnect();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error starting daemon:', error.message);
|
console.error('Error starting daemon:', handleError(error).message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -139,7 +139,7 @@ export function registerDaemonCommand(smartcli: plugins.smartcli.Smartcli) {
|
|||||||
// Disconnect from the daemon after stopping
|
// Disconnect from the daemon after stopping
|
||||||
await tspmIpcClient.disconnect();
|
await tspmIpcClient.disconnect();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error stopping daemon:', error.message);
|
console.error('Error stopping daemon:', handleError(error).message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -169,7 +169,7 @@ export function registerDaemonCommand(smartcli: plugins.smartcli.Smartcli) {
|
|||||||
// Disconnect from daemon after getting status
|
// Disconnect from daemon after getting status
|
||||||
await tspmIpcClient.disconnect();
|
await tspmIpcClient.disconnect();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting daemon status:', error.message);
|
console.error('Error getting daemon status:', handleError(error).message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { formatMemory } from '../helpers/memory.js';
|
|||||||
|
|
||||||
export function registerDefaultCommand(smartcli: plugins.smartcli.Smartcli) {
|
export function registerDefaultCommand(smartcli: plugins.smartcli.Smartcli) {
|
||||||
const cliLogger = new Logger('CLI');
|
const cliLogger = new Logger('CLI');
|
||||||
const tspmProjectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir);
|
|
||||||
|
|
||||||
smartcli.standardCommand().subscribe({
|
smartcli.standardCommand().subscribe({
|
||||||
next: async (argvArg: CliArguments) => {
|
next: async (argvArg: CliArguments) => {
|
||||||
|
const tspmProjectinfo = await plugins.projectinfo.ProjectInfo.create(paths.packageDir);
|
||||||
console.log(
|
console.log(
|
||||||
`TSPM - TypeScript Process Manager v${tspmProjectinfo.npm.version}`,
|
`TSPM - TypeScript Process Manager v${tspmProjectinfo.npm.version}`,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as plugins from '../../plugins.js';
|
import * as plugins from '../../plugins.js';
|
||||||
import { TspmServiceManager } from '../../../client/tspm.servicemanager.js';
|
import { TspmServiceManager } from '../../../client/tspm.servicemanager.js';
|
||||||
import { Logger } from '../../../shared/common/utils.errorhandler.js';
|
import { handleError, Logger } from '../../../shared/common/utils.errorhandler.js';
|
||||||
import type { CliArguments } from '../../types.js';
|
import type { CliArguments } from '../../types.js';
|
||||||
|
|
||||||
export function registerDisableCommand(smartcli: plugins.smartcli.Smartcli) {
|
export function registerDisableCommand(smartcli: plugins.smartcli.Smartcli) {
|
||||||
@@ -18,10 +18,11 @@ export function registerDisableCommand(smartcli: plugins.smartcli.Smartcli) {
|
|||||||
console.log(' The daemon will no longer start on system boot');
|
console.log(' The daemon will no longer start on system boot');
|
||||||
console.log(' Use "tspm enable" to re-enable the service');
|
console.log(' Use "tspm enable" to re-enable the service');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error disabling service:', error.message);
|
const errorMessage = handleError(error).message;
|
||||||
|
console.error('Error disabling service:', errorMessage);
|
||||||
if (
|
if (
|
||||||
error.message.includes('permission') ||
|
errorMessage.includes('permission') ||
|
||||||
error.message.includes('denied')
|
errorMessage.includes('denied')
|
||||||
) {
|
) {
|
||||||
console.log('\nNote: You may need to run this command with sudo');
|
console.log('\nNote: You may need to run this command with sudo');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as plugins from '../../plugins.js';
|
import * as plugins from '../../plugins.js';
|
||||||
import { TspmServiceManager } from '../../../client/tspm.servicemanager.js';
|
import { TspmServiceManager } from '../../../client/tspm.servicemanager.js';
|
||||||
import { Logger } from '../../../shared/common/utils.errorhandler.js';
|
import { handleError, Logger } from '../../../shared/common/utils.errorhandler.js';
|
||||||
import type { CliArguments } from '../../types.js';
|
import type { CliArguments } from '../../types.js';
|
||||||
|
|
||||||
export function registerEnableCommand(smartcli: plugins.smartcli.Smartcli) {
|
export function registerEnableCommand(smartcli: plugins.smartcli.Smartcli) {
|
||||||
@@ -18,10 +18,11 @@ export function registerEnableCommand(smartcli: plugins.smartcli.Smartcli) {
|
|||||||
console.log(' The daemon will now start automatically on system boot');
|
console.log(' The daemon will now start automatically on system boot');
|
||||||
console.log(' Use "tspm disable" to remove the service');
|
console.log(' Use "tspm disable" to remove the service');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error enabling service:', error.message);
|
const errorMessage = handleError(error).message;
|
||||||
|
console.error('Error enabling service:', errorMessage);
|
||||||
if (
|
if (
|
||||||
error.message.includes('permission') ||
|
errorMessage.includes('permission') ||
|
||||||
error.message.includes('denied')
|
errorMessage.includes('denied')
|
||||||
) {
|
) {
|
||||||
console.log('\nNote: You may need to run this command with sudo');
|
console.log('\nNote: You may need to run this command with sudo');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export async function interactiveEditProcess(processId: number): Promise<void> {
|
|||||||
message: 'Process name:',
|
message: 'Process name:',
|
||||||
default: config.name,
|
default: config.name,
|
||||||
validate: (input: string) => {
|
validate: (input: string) => {
|
||||||
return input && input.trim() !== '';
|
return input.trim() !== '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -23,7 +23,7 @@ export async function interactiveEditProcess(processId: number): Promise<void> {
|
|||||||
message: 'Command to execute:',
|
message: 'Command to execute:',
|
||||||
default: config.command,
|
default: config.command,
|
||||||
validate: (input: string) => {
|
validate: (input: string) => {
|
||||||
return input && input.trim() !== '';
|
return input.trim() !== '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -32,7 +32,7 @@ export async function interactiveEditProcess(processId: number): Promise<void> {
|
|||||||
message: 'Working directory:',
|
message: 'Working directory:',
|
||||||
default: config.projectDir,
|
default: config.projectDir,
|
||||||
validate: (input: string) => {
|
validate: (input: string) => {
|
||||||
return input && input.trim() !== '';
|
return input.trim() !== '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ export type { CliArguments } from './types.js';
|
|||||||
*/
|
*/
|
||||||
export const run = async (): Promise<void> => {
|
export const run = async (): Promise<void> => {
|
||||||
const cliLogger = new Logger('CLI');
|
const cliLogger = new Logger('CLI');
|
||||||
const tspmProjectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir);
|
const tspmProjectinfo = await plugins.projectinfo.ProjectInfo.create(paths.packageDir);
|
||||||
|
|
||||||
// Check if debug mode is enabled
|
// Check if debug mode is enabled
|
||||||
const debugMode = process.env.TSPM_DEBUG === 'true';
|
const debugMode = process.env.TSPM_DEBUG === 'true';
|
||||||
|
|||||||
+17
-15
@@ -3,6 +3,7 @@ import * as paths from '../paths.js';
|
|||||||
import { toProcessId } from '../shared/protocol/id.js';
|
import { toProcessId } from '../shared/protocol/id.js';
|
||||||
import type { ProcessId } from '../shared/protocol/id.js';
|
import type { ProcessId } from '../shared/protocol/id.js';
|
||||||
import { ProcessManager } from './processmanager.js';
|
import { ProcessManager } from './processmanager.js';
|
||||||
|
import { handleError } from '../shared/common/utils.errorhandler.js';
|
||||||
import type {
|
import type {
|
||||||
IpcMethodMap,
|
IpcMethodMap,
|
||||||
RequestForMethod,
|
RequestForMethod,
|
||||||
@@ -17,7 +18,7 @@ import { LogPersistence } from './logpersistence.js';
|
|||||||
*/
|
*/
|
||||||
export class TspmDaemon {
|
export class TspmDaemon {
|
||||||
private tspmInstance: ProcessManager;
|
private tspmInstance: ProcessManager;
|
||||||
private ipcServer: plugins.smartipc.IpcServer;
|
private ipcServer!: plugins.smartipc.IpcServer;
|
||||||
private startTime: number;
|
private startTime: number;
|
||||||
private isShuttingDown: boolean = false;
|
private isShuttingDown: boolean = false;
|
||||||
private socketPath: string;
|
private socketPath: string;
|
||||||
@@ -30,13 +31,7 @@ export class TspmDaemon {
|
|||||||
this.socketPath = plugins.path.join(paths.tspmDir, 'tspm.sock');
|
this.socketPath = plugins.path.join(paths.tspmDir, 'tspm.sock');
|
||||||
this.daemonPidFile = plugins.path.join(paths.tspmDir, 'daemon.pid');
|
this.daemonPidFile = plugins.path.join(paths.tspmDir, 'daemon.pid');
|
||||||
this.startTime = Date.now();
|
this.startTime = Date.now();
|
||||||
// Determine daemon version from package metadata
|
this.version = 'unknown';
|
||||||
try {
|
|
||||||
const proj = new plugins.projectinfo.ProjectInfo(paths.packageDir);
|
|
||||||
this.version = proj.npm.version || 'unknown';
|
|
||||||
} catch {
|
|
||||||
this.version = 'unknown';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,6 +40,13 @@ export class TspmDaemon {
|
|||||||
public async start(): Promise<void> {
|
public async start(): Promise<void> {
|
||||||
console.log('Starting TSPM daemon...');
|
console.log('Starting TSPM daemon...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const proj = await plugins.projectinfo.ProjectInfo.create(paths.packageDir);
|
||||||
|
this.version = proj.npm.version || 'unknown';
|
||||||
|
} catch {
|
||||||
|
this.version = 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure the TSPM directory exists
|
// Ensure the TSPM directory exists
|
||||||
const fs = await import('fs/promises');
|
const fs = await import('fs/promises');
|
||||||
await fs.mkdir(paths.tspmDir, { recursive: true });
|
await fs.mkdir(paths.tspmDir, { recursive: true });
|
||||||
@@ -150,7 +152,7 @@ export class TspmDaemon {
|
|||||||
status: processInfo?.status || 'stopped',
|
status: processInfo?.status || 'stopped',
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Failed to start process: ${error.message}`);
|
throw new Error(`Failed to start process: ${handleError(error).message}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -194,7 +196,7 @@ export class TspmDaemon {
|
|||||||
status: processInfo?.status || 'stopped',
|
status: processInfo?.status || 'stopped',
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Failed to start process: ${error.message}`);
|
throw new Error(`Failed to start process: ${handleError(error).message}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -211,7 +213,7 @@ export class TspmDaemon {
|
|||||||
message: `Process ${id} stopped successfully`,
|
message: `Process ${id} stopped successfully`,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Failed to stop process: ${error.message}`);
|
throw new Error(`Failed to stop process: ${handleError(error).message}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -230,7 +232,7 @@ export class TspmDaemon {
|
|||||||
status: processInfo?.status || 'stopped',
|
status: processInfo?.status || 'stopped',
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Failed to restart process: ${error.message}`);
|
throw new Error(`Failed to restart process: ${handleError(error).message}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -248,7 +250,7 @@ export class TspmDaemon {
|
|||||||
message: `Process ${id} deleted successfully`,
|
message: `Process ${id} deleted successfully`,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Failed to delete process: ${error.message}`);
|
throw new Error(`Failed to delete process: ${handleError(error).message}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -262,7 +264,7 @@ export class TspmDaemon {
|
|||||||
const config = this.tspmInstance.processConfigs.get(id)!;
|
const config = this.tspmInstance.processConfigs.get(id)!;
|
||||||
return { id, config };
|
return { id, config };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Failed to add process: ${error.message}`);
|
throw new Error(`Failed to add process: ${handleError(error).message}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -275,7 +277,7 @@ export class TspmDaemon {
|
|||||||
const updated = await this.tspmInstance.update(id, request.updates as any);
|
const updated = await this.tspmInstance.update(id, request.updates as any);
|
||||||
return { id, config: updated };
|
return { id, config: updated };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`Failed to update process: ${error.message}`);
|
throw new Error(`Failed to update process: ${handleError(error).message}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
+1
-3
@@ -7,9 +7,7 @@
|
|||||||
"module": "NodeNext",
|
"module": "NodeNext",
|
||||||
"moduleResolution": "NodeNext",
|
"moduleResolution": "NodeNext",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {}
|
|
||||||
},
|
},
|
||||||
"exclude": ["dist_*/**/*.d.ts"]
|
"exclude": ["dist_*/**/*.d.ts"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user