bs9 1.4.6 → 1.5.0
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 +17 -1
- package/bin/bs9 +11 -10
- package/dist/bs9-cbcmk6jy. +389 -0
- package/dist/bs9-cd3btjpw. +312 -0
- package/dist/bs9-hp4w75sv. +281 -0
- package/dist/bs9-ws85s3p9. +270 -0
- package/dist/bs9-xaw2xcxz. +270 -0
- package/dist/bs9.js +1 -1
- package/package.json +1 -1
- package/src/commands/delete.ts +79 -2
- package/src/commands/restart.ts +77 -1
- package/src/commands/start.ts +93 -1
- package/src/commands/status.ts +163 -110
- package/src/commands/stop.ts +77 -1
- package/src/utils/array-parser.ts +131 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { join, dirname } from "node:path";
|
|
6
|
+
|
|
7
|
+
// Read version from package.json
|
|
8
|
+
const packageJsonPath = join(dirname(import.meta.path), '..', 'package.json');
|
|
9
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
10
|
+
const version = packageJson.version;
|
|
11
|
+
|
|
12
|
+
import { startCommand } from "../src/commands/start.js";
|
|
13
|
+
import { stopCommand } from "../src/commands/stop.js";
|
|
14
|
+
import { restartCommand } from "../src/commands/restart.js";
|
|
15
|
+
import { statusCommand } from "../src/commands/status.js";
|
|
16
|
+
import { logsCommand } from "../src/commands/logs.js";
|
|
17
|
+
import { monitCommand } from "../src/commands/monit.js";
|
|
18
|
+
import { webCommand } from "../src/commands/web.js";
|
|
19
|
+
import { alertCommand } from "../src/commands/alert.js";
|
|
20
|
+
import { exportCommand } from "../src/commands/export.js";
|
|
21
|
+
import { depsCommand } from "../src/commands/deps.js";
|
|
22
|
+
import { profileCommand } from "../src/commands/profile.js";
|
|
23
|
+
import { deleteCommand } from "../src/commands/delete.js";
|
|
24
|
+
import { saveCommand } from "../src/commands/save.js";
|
|
25
|
+
import { resurrectCommand } from "../src/commands/resurrect.js";
|
|
26
|
+
import { deployCommand } from "../src/commands/deploy.js";
|
|
27
|
+
import { loadbalancerCommand } from "../src/loadbalancer/manager.js";
|
|
28
|
+
import { windowsCommand } from "../src/windows/service.js";
|
|
29
|
+
import { launchdCommand } from "../src/macos/launchd.js";
|
|
30
|
+
import { updateCommand } from "../src/commands/update.js";
|
|
31
|
+
import { dbpoolCommand } from "../src/database/pool.js";
|
|
32
|
+
import { advancedMonitoringCommand } from "../src/monitoring/advanced.js";
|
|
33
|
+
import { consulCommand } from "../src/discovery/consul.js";
|
|
34
|
+
import { doctorCommand } from "../src/commands/doctor.js";
|
|
35
|
+
import { inspectCommand } from "../src/commands/inspect.js";
|
|
36
|
+
|
|
37
|
+
const program = new Command();
|
|
38
|
+
|
|
39
|
+
program
|
|
40
|
+
.name("bs9")
|
|
41
|
+
.description("BS9 (Bun Sentinel 9) — Mission-critical process manager CLI")
|
|
42
|
+
.version(version);
|
|
43
|
+
|
|
44
|
+
program
|
|
45
|
+
.command("start")
|
|
46
|
+
.description("Start one or more services")
|
|
47
|
+
.argument("[file...]", "Application file, service name, array [app1,app2], pattern [app-*], or [all]")
|
|
48
|
+
.option("-n, --name <name>", "Service name")
|
|
49
|
+
.option("-p, --port <port>", "Port number", "3000")
|
|
50
|
+
.option("-h, --host <host>", "Host address", "localhost")
|
|
51
|
+
.option("--https", "Use HTTPS protocol")
|
|
52
|
+
.option("-e, --env <env>", "Environment variables (can be used multiple times)", (value, previous) => [...(previous || []), value])
|
|
53
|
+
.option("--otel", "Enable OpenTelemetry instrumentation", true)
|
|
54
|
+
.option("--prometheus", "Enable Prometheus metrics", true)
|
|
55
|
+
.option("--build", "Build TypeScript to JavaScript before starting")
|
|
56
|
+
.action(startCommand);
|
|
57
|
+
|
|
58
|
+
program
|
|
59
|
+
.command("stop")
|
|
60
|
+
.description("Stop one or more services")
|
|
61
|
+
.argument("[name...]", "Service name, array [app1,app2], pattern [app-*], or [all]")
|
|
62
|
+
.action(stopCommand);
|
|
63
|
+
|
|
64
|
+
program
|
|
65
|
+
.command("restart")
|
|
66
|
+
.description("Restart one or more services")
|
|
67
|
+
.argument("[name...]", "Service name, array [app1,app2], pattern [app-*], or [all]")
|
|
68
|
+
.action(restartCommand);
|
|
69
|
+
|
|
70
|
+
program
|
|
71
|
+
.command("status")
|
|
72
|
+
.description("Show status and SRE metrics for services")
|
|
73
|
+
.argument("[name...]", "Service name, array [app1,app2], pattern [app-*], or [all]")
|
|
74
|
+
.option("-w, --watch", "Watch mode (refresh every 2s)")
|
|
75
|
+
.action(statusCommand);
|
|
76
|
+
|
|
77
|
+
program
|
|
78
|
+
.command("logs")
|
|
79
|
+
.description("Show logs for a service (via journalctl)")
|
|
80
|
+
.argument("<name>", "Service name")
|
|
81
|
+
.option("-f, --follow", "Follow logs")
|
|
82
|
+
.option("-n, --lines <number>", "Number of lines", "50")
|
|
83
|
+
.action(logsCommand);
|
|
84
|
+
|
|
85
|
+
program
|
|
86
|
+
.command("monit")
|
|
87
|
+
.description("Real-time terminal dashboard for all services")
|
|
88
|
+
.option("-r, --refresh <seconds>", "Refresh interval in seconds", "2")
|
|
89
|
+
.action(monitCommand);
|
|
90
|
+
|
|
91
|
+
program
|
|
92
|
+
.command("web")
|
|
93
|
+
.description("Start web-based monitoring dashboard")
|
|
94
|
+
.option("-p, --port <port>", "Port for web dashboard", "8080")
|
|
95
|
+
.option("-d, --detach", "Run in background")
|
|
96
|
+
.action(webCommand);
|
|
97
|
+
|
|
98
|
+
program
|
|
99
|
+
.command("alert")
|
|
100
|
+
.description("Configure alert thresholds and webhooks")
|
|
101
|
+
.option("--enable", "Enable alerts")
|
|
102
|
+
.option("--disable", "Disable alerts")
|
|
103
|
+
.option("--webhook <url>", "Set webhook URL for alerts")
|
|
104
|
+
.option("--cpu <percentage>", "CPU threshold percentage")
|
|
105
|
+
.option("--memory <percentage>", "Memory threshold percentage")
|
|
106
|
+
.option("--errorRate <percentage>", "Error rate threshold percentage")
|
|
107
|
+
.option("--uptime <percentage>", "Uptime threshold percentage")
|
|
108
|
+
.option("--cooldown <seconds>", "Alert cooldown period in seconds")
|
|
109
|
+
.option("--service <name>", "Configure alerts for specific service")
|
|
110
|
+
.option("--list", "List current alert configuration")
|
|
111
|
+
.option("--test", "Test webhook connectivity")
|
|
112
|
+
.action(alertCommand);
|
|
113
|
+
|
|
114
|
+
program
|
|
115
|
+
.command("export")
|
|
116
|
+
.description("Export historical metrics data")
|
|
117
|
+
.option("-f, --format <format>", "Export format (json|csv)", "json")
|
|
118
|
+
.option("-h, --hours <hours>", "Hours of data to export", "24")
|
|
119
|
+
.option("-o, --output <file>", "Output file path")
|
|
120
|
+
.option("-s, --service <name>", "Export specific service metrics")
|
|
121
|
+
.action(exportCommand);
|
|
122
|
+
|
|
123
|
+
program
|
|
124
|
+
.command("deps")
|
|
125
|
+
.description("Visualize service dependencies")
|
|
126
|
+
.option("-f, --format <format>", "Output format (text|dot|json)", "text")
|
|
127
|
+
.option("-o, --output <file>", "Output file path")
|
|
128
|
+
.action(depsCommand);
|
|
129
|
+
|
|
130
|
+
program
|
|
131
|
+
.command("profile")
|
|
132
|
+
.description("Performance profiling for services")
|
|
133
|
+
.option("-d, --duration <seconds>", "Profiling duration", "60")
|
|
134
|
+
.option("-i, --interval <ms>", "Sampling interval", "1000")
|
|
135
|
+
.option("-s, --service <name>", "Service name to profile")
|
|
136
|
+
.option("--flamegraph", "Generate flame graph")
|
|
137
|
+
.option("--top <number>", "Show top N functions", "10")
|
|
138
|
+
.action(profileCommand);
|
|
139
|
+
|
|
140
|
+
program
|
|
141
|
+
.command("delete")
|
|
142
|
+
.description("Delete one or more managed services")
|
|
143
|
+
.argument("[name...]", "Service name, array [app1,app2], pattern [test-*], or [all]")
|
|
144
|
+
.option("-a, --all", "Delete all services")
|
|
145
|
+
.option("-f, --force", "Force deletion without confirmation")
|
|
146
|
+
.option("-r, --remove", "Remove service configuration files")
|
|
147
|
+
.option("-t, --timeout <seconds>", "Timeout for graceful shutdown (default: 30)")
|
|
148
|
+
.action(deleteCommand);
|
|
149
|
+
|
|
150
|
+
program
|
|
151
|
+
.command("save")
|
|
152
|
+
.description("Save service configurations to backup")
|
|
153
|
+
.argument("[name]", "Service name (optional)")
|
|
154
|
+
.option("-a, --all", "Save all services")
|
|
155
|
+
.option("-f, --force", "Force save without errors")
|
|
156
|
+
.option("-b, --backup", "Create timestamped backup")
|
|
157
|
+
.action(saveCommand);
|
|
158
|
+
|
|
159
|
+
program
|
|
160
|
+
.command("resurrect")
|
|
161
|
+
.description("Resurrect services from backup")
|
|
162
|
+
.argument("[name]", "Service name (optional)")
|
|
163
|
+
.option("-a, --all", "Resurrect all services")
|
|
164
|
+
.option("-f, --force", "Force resurrection without errors")
|
|
165
|
+
.option("-c, --config <file>", "Configuration file to use")
|
|
166
|
+
.action(resurrectCommand);
|
|
167
|
+
|
|
168
|
+
program
|
|
169
|
+
.command("deploy")
|
|
170
|
+
.description("🚀 Deploy applications with zero-config production setup")
|
|
171
|
+
.argument("<file>", "Application file to deploy")
|
|
172
|
+
.option("-n, --name <name>", "Service name")
|
|
173
|
+
.option("-p, --port <port>", "Port number", "3000")
|
|
174
|
+
.option("-h, --host <host>", "Host address", "localhost")
|
|
175
|
+
.option("-e, --env <env>", "Environment variables (multiple)", (value, previous) => [...(previous || []), value])
|
|
176
|
+
.option("-i, --instances <number>", "Number of instances")
|
|
177
|
+
.option("--memory <memory>", "Memory limit")
|
|
178
|
+
.option("--cpu <cpu>", "CPU limit")
|
|
179
|
+
.option("--log-level <level>", "Log level")
|
|
180
|
+
.option("--log-file <file>", "Log file path")
|
|
181
|
+
.option("--restart <policy>", "Restart policy")
|
|
182
|
+
.option("--no-health", "Skip health check")
|
|
183
|
+
.option("--no-metrics", "Disable metrics")
|
|
184
|
+
.option("--no-otel", "Disable OpenTelemetry")
|
|
185
|
+
.option("--no-prometheus", "Disable Prometheus")
|
|
186
|
+
.option("--https", "Enable HTTPS")
|
|
187
|
+
.option("--no-linger", "Don't enable linger")
|
|
188
|
+
.option("-f, --force", "Force deployment")
|
|
189
|
+
.option("--reload", "Reload existing service")
|
|
190
|
+
.option("--build", "Build TypeScript")
|
|
191
|
+
.action(deployCommand);
|
|
192
|
+
|
|
193
|
+
program
|
|
194
|
+
.command("loadbalancer")
|
|
195
|
+
.description("Load balancer management")
|
|
196
|
+
.argument("<action>", "Action to perform")
|
|
197
|
+
.option("-p, --port <port>", "Load balancer port", "8080")
|
|
198
|
+
.option("-a, --algorithm <type>", "Load balancing algorithm", "round-robin")
|
|
199
|
+
.option("-b, --backends <list>", "Backend servers (host:port,host:port)")
|
|
200
|
+
.option("--health-check", "Enable health checking", true)
|
|
201
|
+
.option("--health-path <path>", "Health check path", "/healthz")
|
|
202
|
+
.option("--health-interval <ms>", "Health check interval", "10000")
|
|
203
|
+
.action(loadbalancerCommand);
|
|
204
|
+
|
|
205
|
+
program
|
|
206
|
+
.command("dbpool")
|
|
207
|
+
.description("Database connection pool management")
|
|
208
|
+
.argument("<action>", "Action to perform")
|
|
209
|
+
.option("--host <host>", "Database host", "localhost")
|
|
210
|
+
.option("--port <port>", "Database port", "5432")
|
|
211
|
+
.option("--database <name>", "Database name", "testdb")
|
|
212
|
+
.option("--username <user>", "Database username", "user")
|
|
213
|
+
.option("--password <pass>", "Database password", "password")
|
|
214
|
+
.option("--max-connections <num>", "Maximum connections", "10")
|
|
215
|
+
.option("--min-connections <num>", "Minimum connections", "2")
|
|
216
|
+
.option("--concurrency <num>", "Test concurrency", "10")
|
|
217
|
+
.option("--iterations <num>", "Test iterations", "100")
|
|
218
|
+
.action(dbpoolCommand);
|
|
219
|
+
|
|
220
|
+
program
|
|
221
|
+
.command("update")
|
|
222
|
+
.description("Update BS9 to latest version")
|
|
223
|
+
.option("--check", "Check for updates without installing")
|
|
224
|
+
.option("--force", "Force update even if already latest")
|
|
225
|
+
.option("--rollback", "Rollback to previous version")
|
|
226
|
+
.option("--version <version>", "Update to specific version")
|
|
227
|
+
.action(updateCommand);
|
|
228
|
+
|
|
229
|
+
program
|
|
230
|
+
.command("advanced")
|
|
231
|
+
.description("Advanced monitoring dashboard")
|
|
232
|
+
.option("--port <port>", "Dashboard port", "8090")
|
|
233
|
+
.action(advancedMonitoringCommand);
|
|
234
|
+
|
|
235
|
+
program
|
|
236
|
+
.command("consul")
|
|
237
|
+
.description("Consul service discovery")
|
|
238
|
+
.argument("<action>", "Action to perform")
|
|
239
|
+
.option("--consul-url <url>", "Consul URL", "http://localhost:8500")
|
|
240
|
+
.option("--name <name>", "Service name")
|
|
241
|
+
.option("--id <id>", "Service ID")
|
|
242
|
+
.option("--address <address>", "Service address")
|
|
243
|
+
.option("--port <port>", "Service port")
|
|
244
|
+
.option("--tags <tags>", "Service tags (comma-separated)")
|
|
245
|
+
.option("--health-check <url>", "Health check URL")
|
|
246
|
+
.option("--meta <json>", "Service metadata (JSON)")
|
|
247
|
+
.option("--service <service>", "Service name for discovery")
|
|
248
|
+
.action(consulCommand);
|
|
249
|
+
|
|
250
|
+
program
|
|
251
|
+
.command("doctor")
|
|
252
|
+
.description("Perform comprehensive health check")
|
|
253
|
+
.option("--check <type>", "Specific check to run (dependencies|configuration|platform)")
|
|
254
|
+
.option("-v, --verbose", "Verbose output with system information")
|
|
255
|
+
.action(doctorCommand);
|
|
256
|
+
|
|
257
|
+
program
|
|
258
|
+
.command("inspect")
|
|
259
|
+
.description("Comprehensive system inspection and analysis")
|
|
260
|
+
.option("--security", "Security inspection only")
|
|
261
|
+
.option("--performance", "Performance inspection only")
|
|
262
|
+
.option("--configuration", "Configuration inspection only")
|
|
263
|
+
.option("--compliance", "Compliance inspection only")
|
|
264
|
+
.option("--full", "Complete system inspection")
|
|
265
|
+
.option("--report <format>", "Export report (json|csv)")
|
|
266
|
+
.option("--deep", "Deep system analysis")
|
|
267
|
+
.option("-v, --verbose", "Verbose output with detailed analysis")
|
|
268
|
+
.action(inspectCommand);
|
|
269
|
+
|
|
270
|
+
program.parse();
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { join, dirname } from "node:path";
|
|
6
|
+
|
|
7
|
+
// Read version from package.json
|
|
8
|
+
const packageJsonPath = join(dirname(import.meta.path), '..', 'package.json');
|
|
9
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
10
|
+
const version = packageJson.version;
|
|
11
|
+
|
|
12
|
+
import { startCommand } from "../src/commands/start.js";
|
|
13
|
+
import { stopCommand } from "../src/commands/stop.js";
|
|
14
|
+
import { restartCommand } from "../src/commands/restart.js";
|
|
15
|
+
import { statusCommand } from "../src/commands/status.js";
|
|
16
|
+
import { logsCommand } from "../src/commands/logs.js";
|
|
17
|
+
import { monitCommand } from "../src/commands/monit.js";
|
|
18
|
+
import { webCommand } from "../src/commands/web.js";
|
|
19
|
+
import { alertCommand } from "../src/commands/alert.js";
|
|
20
|
+
import { exportCommand } from "../src/commands/export.js";
|
|
21
|
+
import { depsCommand } from "../src/commands/deps.js";
|
|
22
|
+
import { profileCommand } from "../src/commands/profile.js";
|
|
23
|
+
import { deleteCommand } from "../src/commands/delete.js";
|
|
24
|
+
import { saveCommand } from "../src/commands/save.js";
|
|
25
|
+
import { resurrectCommand } from "../src/commands/resurrect.js";
|
|
26
|
+
import { deployCommand } from "../src/commands/deploy.js";
|
|
27
|
+
import { loadbalancerCommand } from "../src/loadbalancer/manager.js";
|
|
28
|
+
import { windowsCommand } from "../src/windows/service.js";
|
|
29
|
+
import { launchdCommand } from "../src/macos/launchd.js";
|
|
30
|
+
import { updateCommand } from "../src/commands/update.js";
|
|
31
|
+
import { dbpoolCommand } from "../src/database/pool.js";
|
|
32
|
+
import { advancedMonitoringCommand } from "../src/monitoring/advanced.js";
|
|
33
|
+
import { consulCommand } from "../src/discovery/consul.js";
|
|
34
|
+
import { doctorCommand } from "../src/commands/doctor.js";
|
|
35
|
+
import { inspectCommand } from "../src/commands/inspect.js";
|
|
36
|
+
|
|
37
|
+
const program = new Command();
|
|
38
|
+
|
|
39
|
+
program
|
|
40
|
+
.name("bs9")
|
|
41
|
+
.description("BS9 (Bun Sentinel 9) — Mission-critical process manager CLI")
|
|
42
|
+
.version(version);
|
|
43
|
+
|
|
44
|
+
program
|
|
45
|
+
.command("start")
|
|
46
|
+
.description("Start one or more services")
|
|
47
|
+
.argument("[file]", "Application file, service name, array [app1,app2], pattern [app-*], or [all]")
|
|
48
|
+
.option("-n, --name <name>", "Service name")
|
|
49
|
+
.option("-p, --port <port>", "Port number", "3000")
|
|
50
|
+
.option("-h, --host <host>", "Host address", "localhost")
|
|
51
|
+
.option("--https", "Use HTTPS protocol")
|
|
52
|
+
.option("-e, --env <env>", "Environment variables (can be used multiple times)", (value, previous) => [...(previous || []), value])
|
|
53
|
+
.option("--otel", "Enable OpenTelemetry instrumentation", true)
|
|
54
|
+
.option("--prometheus", "Enable Prometheus metrics", true)
|
|
55
|
+
.option("--build", "Build TypeScript to JavaScript before starting")
|
|
56
|
+
.action(startCommand);
|
|
57
|
+
|
|
58
|
+
program
|
|
59
|
+
.command("stop")
|
|
60
|
+
.description("Stop one or more services")
|
|
61
|
+
.argument("[name]", "Service name, array [app1,app2], pattern [app-*], or [all]")
|
|
62
|
+
.action(stopCommand);
|
|
63
|
+
|
|
64
|
+
program
|
|
65
|
+
.command("restart")
|
|
66
|
+
.description("Restart one or more services")
|
|
67
|
+
.argument("[name]", "Service name, array [app1,app2], pattern [app-*], or [all]")
|
|
68
|
+
.action(restartCommand);
|
|
69
|
+
|
|
70
|
+
program
|
|
71
|
+
.command("status")
|
|
72
|
+
.description("Show status and SRE metrics for services")
|
|
73
|
+
.argument("[name]", "Service name, array [app1,app2], pattern [app-*], or [all]")
|
|
74
|
+
.option("-w, --watch", "Watch mode (refresh every 2s)")
|
|
75
|
+
.action(statusCommand);
|
|
76
|
+
|
|
77
|
+
program
|
|
78
|
+
.command("logs")
|
|
79
|
+
.description("Show logs for a service (via journalctl)")
|
|
80
|
+
.argument("<name>", "Service name")
|
|
81
|
+
.option("-f, --follow", "Follow logs")
|
|
82
|
+
.option("-n, --lines <number>", "Number of lines", "50")
|
|
83
|
+
.action(logsCommand);
|
|
84
|
+
|
|
85
|
+
program
|
|
86
|
+
.command("monit")
|
|
87
|
+
.description("Real-time terminal dashboard for all services")
|
|
88
|
+
.option("-r, --refresh <seconds>", "Refresh interval in seconds", "2")
|
|
89
|
+
.action(monitCommand);
|
|
90
|
+
|
|
91
|
+
program
|
|
92
|
+
.command("web")
|
|
93
|
+
.description("Start web-based monitoring dashboard")
|
|
94
|
+
.option("-p, --port <port>", "Port for web dashboard", "8080")
|
|
95
|
+
.option("-d, --detach", "Run in background")
|
|
96
|
+
.action(webCommand);
|
|
97
|
+
|
|
98
|
+
program
|
|
99
|
+
.command("alert")
|
|
100
|
+
.description("Configure alert thresholds and webhooks")
|
|
101
|
+
.option("--enable", "Enable alerts")
|
|
102
|
+
.option("--disable", "Disable alerts")
|
|
103
|
+
.option("--webhook <url>", "Set webhook URL for alerts")
|
|
104
|
+
.option("--cpu <percentage>", "CPU threshold percentage")
|
|
105
|
+
.option("--memory <percentage>", "Memory threshold percentage")
|
|
106
|
+
.option("--errorRate <percentage>", "Error rate threshold percentage")
|
|
107
|
+
.option("--uptime <percentage>", "Uptime threshold percentage")
|
|
108
|
+
.option("--cooldown <seconds>", "Alert cooldown period in seconds")
|
|
109
|
+
.option("--service <name>", "Configure alerts for specific service")
|
|
110
|
+
.option("--list", "List current alert configuration")
|
|
111
|
+
.option("--test", "Test webhook connectivity")
|
|
112
|
+
.action(alertCommand);
|
|
113
|
+
|
|
114
|
+
program
|
|
115
|
+
.command("export")
|
|
116
|
+
.description("Export historical metrics data")
|
|
117
|
+
.option("-f, --format <format>", "Export format (json|csv)", "json")
|
|
118
|
+
.option("-h, --hours <hours>", "Hours of data to export", "24")
|
|
119
|
+
.option("-o, --output <file>", "Output file path")
|
|
120
|
+
.option("-s, --service <name>", "Export specific service metrics")
|
|
121
|
+
.action(exportCommand);
|
|
122
|
+
|
|
123
|
+
program
|
|
124
|
+
.command("deps")
|
|
125
|
+
.description("Visualize service dependencies")
|
|
126
|
+
.option("-f, --format <format>", "Output format (text|dot|json)", "text")
|
|
127
|
+
.option("-o, --output <file>", "Output file path")
|
|
128
|
+
.action(depsCommand);
|
|
129
|
+
|
|
130
|
+
program
|
|
131
|
+
.command("profile")
|
|
132
|
+
.description("Performance profiling for services")
|
|
133
|
+
.option("-d, --duration <seconds>", "Profiling duration", "60")
|
|
134
|
+
.option("-i, --interval <ms>", "Sampling interval", "1000")
|
|
135
|
+
.option("-s, --service <name>", "Service name to profile")
|
|
136
|
+
.option("--flamegraph", "Generate flame graph")
|
|
137
|
+
.option("--top <number>", "Show top N functions", "10")
|
|
138
|
+
.action(profileCommand);
|
|
139
|
+
|
|
140
|
+
program
|
|
141
|
+
.command("delete")
|
|
142
|
+
.description("Delete one or more managed services")
|
|
143
|
+
.argument("[name]", "Service name, array [app1,app2], pattern [test-*], or [all]")
|
|
144
|
+
.option("-a, --all", "Delete all services")
|
|
145
|
+
.option("-f, --force", "Force deletion without confirmation")
|
|
146
|
+
.option("-r, --remove", "Remove service configuration files")
|
|
147
|
+
.option("-t, --timeout <seconds>", "Timeout for graceful shutdown (default: 30)")
|
|
148
|
+
.action(deleteCommand);
|
|
149
|
+
|
|
150
|
+
program
|
|
151
|
+
.command("save")
|
|
152
|
+
.description("Save service configurations to backup")
|
|
153
|
+
.argument("[name]", "Service name (optional)")
|
|
154
|
+
.option("-a, --all", "Save all services")
|
|
155
|
+
.option("-f, --force", "Force save without errors")
|
|
156
|
+
.option("-b, --backup", "Create timestamped backup")
|
|
157
|
+
.action(saveCommand);
|
|
158
|
+
|
|
159
|
+
program
|
|
160
|
+
.command("resurrect")
|
|
161
|
+
.description("Resurrect services from backup")
|
|
162
|
+
.argument("[name]", "Service name (optional)")
|
|
163
|
+
.option("-a, --all", "Resurrect all services")
|
|
164
|
+
.option("-f, --force", "Force resurrection without errors")
|
|
165
|
+
.option("-c, --config <file>", "Configuration file to use")
|
|
166
|
+
.action(resurrectCommand);
|
|
167
|
+
|
|
168
|
+
program
|
|
169
|
+
.command("deploy")
|
|
170
|
+
.description("🚀 Deploy applications with zero-config production setup")
|
|
171
|
+
.argument("<file>", "Application file to deploy")
|
|
172
|
+
.option("-n, --name <name>", "Service name")
|
|
173
|
+
.option("-p, --port <port>", "Port number", "3000")
|
|
174
|
+
.option("-h, --host <host>", "Host address", "localhost")
|
|
175
|
+
.option("-e, --env <env>", "Environment variables (multiple)", (value, previous) => [...(previous || []), value])
|
|
176
|
+
.option("-i, --instances <number>", "Number of instances")
|
|
177
|
+
.option("--memory <memory>", "Memory limit")
|
|
178
|
+
.option("--cpu <cpu>", "CPU limit")
|
|
179
|
+
.option("--log-level <level>", "Log level")
|
|
180
|
+
.option("--log-file <file>", "Log file path")
|
|
181
|
+
.option("--restart <policy>", "Restart policy")
|
|
182
|
+
.option("--no-health", "Skip health check")
|
|
183
|
+
.option("--no-metrics", "Disable metrics")
|
|
184
|
+
.option("--no-otel", "Disable OpenTelemetry")
|
|
185
|
+
.option("--no-prometheus", "Disable Prometheus")
|
|
186
|
+
.option("--https", "Enable HTTPS")
|
|
187
|
+
.option("--no-linger", "Don't enable linger")
|
|
188
|
+
.option("-f, --force", "Force deployment")
|
|
189
|
+
.option("--reload", "Reload existing service")
|
|
190
|
+
.option("--build", "Build TypeScript")
|
|
191
|
+
.action(deployCommand);
|
|
192
|
+
|
|
193
|
+
program
|
|
194
|
+
.command("loadbalancer")
|
|
195
|
+
.description("Load balancer management")
|
|
196
|
+
.argument("<action>", "Action to perform")
|
|
197
|
+
.option("-p, --port <port>", "Load balancer port", "8080")
|
|
198
|
+
.option("-a, --algorithm <type>", "Load balancing algorithm", "round-robin")
|
|
199
|
+
.option("-b, --backends <list>", "Backend servers (host:port,host:port)")
|
|
200
|
+
.option("--health-check", "Enable health checking", true)
|
|
201
|
+
.option("--health-path <path>", "Health check path", "/healthz")
|
|
202
|
+
.option("--health-interval <ms>", "Health check interval", "10000")
|
|
203
|
+
.action(loadbalancerCommand);
|
|
204
|
+
|
|
205
|
+
program
|
|
206
|
+
.command("dbpool")
|
|
207
|
+
.description("Database connection pool management")
|
|
208
|
+
.argument("<action>", "Action to perform")
|
|
209
|
+
.option("--host <host>", "Database host", "localhost")
|
|
210
|
+
.option("--port <port>", "Database port", "5432")
|
|
211
|
+
.option("--database <name>", "Database name", "testdb")
|
|
212
|
+
.option("--username <user>", "Database username", "user")
|
|
213
|
+
.option("--password <pass>", "Database password", "password")
|
|
214
|
+
.option("--max-connections <num>", "Maximum connections", "10")
|
|
215
|
+
.option("--min-connections <num>", "Minimum connections", "2")
|
|
216
|
+
.option("--concurrency <num>", "Test concurrency", "10")
|
|
217
|
+
.option("--iterations <num>", "Test iterations", "100")
|
|
218
|
+
.action(dbpoolCommand);
|
|
219
|
+
|
|
220
|
+
program
|
|
221
|
+
.command("update")
|
|
222
|
+
.description("Update BS9 to latest version")
|
|
223
|
+
.option("--check", "Check for updates without installing")
|
|
224
|
+
.option("--force", "Force update even if already latest")
|
|
225
|
+
.option("--rollback", "Rollback to previous version")
|
|
226
|
+
.option("--version <version>", "Update to specific version")
|
|
227
|
+
.action(updateCommand);
|
|
228
|
+
|
|
229
|
+
program
|
|
230
|
+
.command("advanced")
|
|
231
|
+
.description("Advanced monitoring dashboard")
|
|
232
|
+
.option("--port <port>", "Dashboard port", "8090")
|
|
233
|
+
.action(advancedMonitoringCommand);
|
|
234
|
+
|
|
235
|
+
program
|
|
236
|
+
.command("consul")
|
|
237
|
+
.description("Consul service discovery")
|
|
238
|
+
.argument("<action>", "Action to perform")
|
|
239
|
+
.option("--consul-url <url>", "Consul URL", "http://localhost:8500")
|
|
240
|
+
.option("--name <name>", "Service name")
|
|
241
|
+
.option("--id <id>", "Service ID")
|
|
242
|
+
.option("--address <address>", "Service address")
|
|
243
|
+
.option("--port <port>", "Service port")
|
|
244
|
+
.option("--tags <tags>", "Service tags (comma-separated)")
|
|
245
|
+
.option("--health-check <url>", "Health check URL")
|
|
246
|
+
.option("--meta <json>", "Service metadata (JSON)")
|
|
247
|
+
.option("--service <service>", "Service name for discovery")
|
|
248
|
+
.action(consulCommand);
|
|
249
|
+
|
|
250
|
+
program
|
|
251
|
+
.command("doctor")
|
|
252
|
+
.description("Perform comprehensive health check")
|
|
253
|
+
.option("--check <type>", "Specific check to run (dependencies|configuration|platform)")
|
|
254
|
+
.option("-v, --verbose", "Verbose output with system information")
|
|
255
|
+
.action(doctorCommand);
|
|
256
|
+
|
|
257
|
+
program
|
|
258
|
+
.command("inspect")
|
|
259
|
+
.description("Comprehensive system inspection and analysis")
|
|
260
|
+
.option("--security", "Security inspection only")
|
|
261
|
+
.option("--performance", "Performance inspection only")
|
|
262
|
+
.option("--configuration", "Configuration inspection only")
|
|
263
|
+
.option("--compliance", "Compliance inspection only")
|
|
264
|
+
.option("--full", "Complete system inspection")
|
|
265
|
+
.option("--report <format>", "Export report (json|csv)")
|
|
266
|
+
.option("--deep", "Deep system analysis")
|
|
267
|
+
.option("-v, --verbose", "Verbose output with detailed analysis")
|
|
268
|
+
.action(inspectCommand);
|
|
269
|
+
|
|
270
|
+
program.parse();
|
package/dist/bs9.js
CHANGED
package/package.json
CHANGED
package/src/commands/delete.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { execSync } from "node:child_process";
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
import { getPlatformInfo } from "../platform/detect.js";
|
|
15
|
+
import { parseServiceArray, confirmAction } from "../utils/array-parser.js";
|
|
15
16
|
|
|
16
17
|
interface DeleteOptions {
|
|
17
18
|
all?: boolean;
|
|
@@ -28,15 +29,66 @@ function isValidServiceName(name: string): boolean {
|
|
|
28
29
|
return validPattern.test(name) && name.length <= 64 && !name.includes('..') && !name.includes('/');
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
export async function deleteCommand(
|
|
32
|
+
export async function deleteCommand(names: string[], options: DeleteOptions): Promise<void> {
|
|
32
33
|
const platformInfo = getPlatformInfo();
|
|
33
34
|
|
|
34
|
-
// Handle
|
|
35
|
+
// Handle multiple arguments
|
|
36
|
+
const name = names.length > 0 ? names.join(' ') : '';
|
|
37
|
+
|
|
38
|
+
// Handle multi-service operations
|
|
39
|
+
if (name.includes('[') || name === 'all') {
|
|
40
|
+
await handleMultiServiceDelete(name, options);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Handle delete all services (legacy)
|
|
35
45
|
if (options.all) {
|
|
36
46
|
await deleteAllServices(platformInfo, options);
|
|
37
47
|
return;
|
|
38
48
|
}
|
|
39
49
|
|
|
50
|
+
// Single service operation (existing logic)
|
|
51
|
+
await handleSingleServiceDelete(name, platformInfo, options);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function handleMultiServiceDelete(name: string, options: DeleteOptions): Promise<void> {
|
|
55
|
+
const services = await parseServiceArray(name);
|
|
56
|
+
|
|
57
|
+
if (services.length === 0) {
|
|
58
|
+
console.log("❌ No services found matching the pattern");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Safety confirmation for bulk operations
|
|
63
|
+
if (!options.force) {
|
|
64
|
+
console.log(`⚠️ About to delete ${services.length} services:`);
|
|
65
|
+
services.forEach(service => console.log(` - ${service}`));
|
|
66
|
+
|
|
67
|
+
const confirmed = await confirmAction('Are you sure? This action cannot be undone. (y/N): ');
|
|
68
|
+
if (!confirmed) {
|
|
69
|
+
console.log('❌ Delete operation cancelled');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log(`🗑️ Deleting ${services.length} services...`);
|
|
75
|
+
|
|
76
|
+
const results = await Promise.allSettled(
|
|
77
|
+
services.map(async (serviceName) => {
|
|
78
|
+
try {
|
|
79
|
+
const platformInfo = getPlatformInfo();
|
|
80
|
+
await handleSingleServiceDelete(serviceName, platformInfo, { ...options, force: true });
|
|
81
|
+
return { service: serviceName, status: 'success', error: null };
|
|
82
|
+
} catch (error) {
|
|
83
|
+
return { service: serviceName, status: 'failed', error: error instanceof Error ? error.message : String(error) };
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
displayBatchResults(results, 'delete');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function handleSingleServiceDelete(name: string, platformInfo: any, options: DeleteOptions): Promise<void> {
|
|
40
92
|
// Security: Validate service name
|
|
41
93
|
if (!isValidServiceName(name)) {
|
|
42
94
|
console.error(`❌ Security: Invalid service name: ${name}`);
|
|
@@ -176,3 +228,28 @@ async function deleteAllServices(platformInfo: any, options: DeleteOptions): Pro
|
|
|
176
228
|
}
|
|
177
229
|
}
|
|
178
230
|
}
|
|
231
|
+
|
|
232
|
+
function displayBatchResults(results: PromiseSettledResult<{ service: string; status: string; error: string | null }>[], operation: string): void {
|
|
233
|
+
console.log(`\n📊 Batch ${operation} Results`);
|
|
234
|
+
console.log("=".repeat(50));
|
|
235
|
+
|
|
236
|
+
const successful = results.filter(r => r.status === 'fulfilled' && r.value.status === 'success');
|
|
237
|
+
const failed = results.filter(r => r.status === 'fulfilled' && r.value.status === 'failed');
|
|
238
|
+
|
|
239
|
+
successful.forEach(result => {
|
|
240
|
+
if (result.status === 'fulfilled') {
|
|
241
|
+
console.log(`✅ ${result.value.service} - ${operation} successful`);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
failed.forEach(result => {
|
|
246
|
+
if (result.status === 'fulfilled') {
|
|
247
|
+
console.log(`❌ ${result.value.service} - Failed: ${result.value.error}`);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
console.log(`\n📈 Summary:`);
|
|
252
|
+
console.log(` Total: ${results.length} services`);
|
|
253
|
+
console.log(` Success: ${successful.length}/${results.length} (${((successful.length / results.length) * 100).toFixed(1)}%)`);
|
|
254
|
+
console.log(` Failed: ${failed.length}/${results.length} (${((failed.length / results.length) * 100).toFixed(1)}%)`);
|
|
255
|
+
}
|