wilfredwake 1.0.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/.env.example +52 -0
- package/LICENSE +21 -0
- package/QUICKSTART.md +400 -0
- package/README.md +831 -0
- package/bin/cli.js +133 -0
- package/index.js +222 -0
- package/package.json +41 -0
- package/src/cli/commands/health.js +238 -0
- package/src/cli/commands/init.js +192 -0
- package/src/cli/commands/status.js +180 -0
- package/src/cli/commands/wake.js +182 -0
- package/src/cli/config.js +263 -0
- package/src/config/services.yaml +49 -0
- package/src/orchestrator/orchestrator.js +397 -0
- package/src/orchestrator/registry.js +283 -0
- package/src/orchestrator/server.js +402 -0
- package/src/shared/colors.js +154 -0
- package/src/shared/logger.js +224 -0
- package/tests/cli.test.js +328 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ╔═══════════════════════════════════════════════════════════════╗
|
|
5
|
+
* ║ ║
|
|
6
|
+
* ║ WILFREDWAKE - CLI TOOL FOR SERVICE ORCHESTRATION ║
|
|
7
|
+
* ║ Multi-Developer Development Environment Management ║
|
|
8
|
+
* ║ ║
|
|
9
|
+
* ║ Entry Point: Main CLI executable with command routing ║
|
|
10
|
+
* ║ Uses Commander.js for robust command-line interface ║
|
|
11
|
+
* ║ ║
|
|
12
|
+
* ╚═══════════════════════════════════════════════════════════════╝
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Command } from 'commander';
|
|
16
|
+
import chalk from 'chalk';
|
|
17
|
+
import { initCommand } from '../src/cli/commands/init.js';
|
|
18
|
+
import { statusCommand } from '../src/cli/commands/status.js';
|
|
19
|
+
import { wakeCommand } from '../src/cli/commands/wake.js';
|
|
20
|
+
import { healthCommand } from '../src/cli/commands/health.js';
|
|
21
|
+
|
|
22
|
+
// ═══════════════════════════════════════════════════════════════
|
|
23
|
+
// MAIN CLI SETUP
|
|
24
|
+
// ═══════════════════════════════════════════════════════════════
|
|
25
|
+
|
|
26
|
+
const program = new Command();
|
|
27
|
+
|
|
28
|
+
program
|
|
29
|
+
.name('wilfredwake')
|
|
30
|
+
.description(
|
|
31
|
+
chalk.cyan('🌅 CLI Tool for Multi-Developer Development Environment Wake & Status Management')
|
|
32
|
+
)
|
|
33
|
+
.version('1.0.0')
|
|
34
|
+
.usage(chalk.yellow('[command] [options]'));
|
|
35
|
+
|
|
36
|
+
// ═══════════════════════════════════════════════════════════════
|
|
37
|
+
// COMMAND REGISTRATION
|
|
38
|
+
// ═══════════════════════════════════════════════════════════════
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* INIT COMMAND
|
|
42
|
+
* Initializes wilfredwake configuration on first-time setup
|
|
43
|
+
* Sets up ~/.wilfredwake directory and config.json
|
|
44
|
+
*/
|
|
45
|
+
program
|
|
46
|
+
.command('init')
|
|
47
|
+
.description(
|
|
48
|
+
chalk.magenta('Initialize wilfredwake configuration (first-time setup)')
|
|
49
|
+
)
|
|
50
|
+
.option('-o, --orchestrator <url>', 'Orchestrator URL', 'http://localhost:3000')
|
|
51
|
+
.option('-t, --token <token>', 'Developer API token')
|
|
52
|
+
.action(initCommand);
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* STATUS COMMAND
|
|
56
|
+
* Displays current status of all services
|
|
57
|
+
* Connects to orchestrator for real-time state
|
|
58
|
+
*/
|
|
59
|
+
program
|
|
60
|
+
.command('status [service]')
|
|
61
|
+
.description(chalk.green('Check status of all services or a specific service'))
|
|
62
|
+
.option('-e, --env <environment>', 'Environment (dev, staging, prod)', 'dev')
|
|
63
|
+
.option('-f, --format <format>', 'Output format (table, json)', 'table')
|
|
64
|
+
.action(statusCommand);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* WAKE COMMAND
|
|
68
|
+
* Wakes services on demand with dependency ordering
|
|
69
|
+
* Defaults to all services if no target specified
|
|
70
|
+
* Supports waking individual services, groups, or all services
|
|
71
|
+
*/
|
|
72
|
+
program
|
|
73
|
+
.command('wake [target]')
|
|
74
|
+
.description(chalk.blue('Wake services on demand (all, <service>, or <group>)'))
|
|
75
|
+
.option('-e, --env <environment>', 'Environment (dev, staging, prod)', 'dev')
|
|
76
|
+
.option('--no-wait', 'Don\'t wait for services to be ready')
|
|
77
|
+
.option('--timeout <seconds>', 'Timeout for service readiness', '300')
|
|
78
|
+
.action(wakeCommand);
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* HEALTH COMMAND
|
|
82
|
+
* Performs health check on services without waking
|
|
83
|
+
* Useful for monitoring and diagnostics
|
|
84
|
+
*/
|
|
85
|
+
program
|
|
86
|
+
.command('health [service]')
|
|
87
|
+
.description(chalk.cyan('Check health status of services'))
|
|
88
|
+
.option('-e, --env <environment>', 'Environment (dev, staging, prod)', 'dev')
|
|
89
|
+
.action(healthCommand);
|
|
90
|
+
|
|
91
|
+
// ═══════════════════════════════════════════════════════════════
|
|
92
|
+
// HELP & ERROR HANDLING
|
|
93
|
+
// ═══════════════════════════════════════════════════════════════
|
|
94
|
+
|
|
95
|
+
// Default help message with visual enhancements
|
|
96
|
+
program.on('--help', () => {
|
|
97
|
+
console.log('');
|
|
98
|
+
console.log(chalk.dim('Examples:'));
|
|
99
|
+
console.log(chalk.yellow(' $ wilfredwake init # Setup configuration'));
|
|
100
|
+
console.log(chalk.yellow(' $ wilfredwake status # Check all services'));
|
|
101
|
+
console.log(chalk.yellow(' $ wilfredwake wake all # Wake all services'));
|
|
102
|
+
console.log(chalk.yellow(' $ wilfredwake wake auth # Wake single service'));
|
|
103
|
+
console.log(chalk.yellow(' $ wilfredwake health # Check health'));
|
|
104
|
+
console.log('');
|
|
105
|
+
console.log(
|
|
106
|
+
chalk.dim(
|
|
107
|
+
'For more information, visit: https://github.com/wilfred/wilfredwake'
|
|
108
|
+
)
|
|
109
|
+
);
|
|
110
|
+
console.log('');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Error handling for unknown commands
|
|
114
|
+
program.on('command:*', () => {
|
|
115
|
+
console.error(
|
|
116
|
+
chalk.red(
|
|
117
|
+
'\n❌ Invalid command. Use --help for available commands.\n'
|
|
118
|
+
)
|
|
119
|
+
);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// ═══════════════════════════════════════════════════════════════
|
|
124
|
+
// CLI EXECUTION
|
|
125
|
+
// ═══════════════════════════════════════════════════════════════
|
|
126
|
+
|
|
127
|
+
// Parse command-line arguments and execute
|
|
128
|
+
program.parse(process.argv);
|
|
129
|
+
|
|
130
|
+
// Show help if no command provided
|
|
131
|
+
if (process.argv.length < 3) {
|
|
132
|
+
program.outputHelp();
|
|
133
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ╔═══════════════════════════════════════════════════════════════╗
|
|
3
|
+
* ║ ║
|
|
4
|
+
* ║ WILFREDWAKE - CLI TOOL FOR SERVICE ORCHESTRATION ║
|
|
5
|
+
* ║ ║
|
|
6
|
+
* ║ Multi-Developer Development Environment Management ║
|
|
7
|
+
* ║ Wake & Status Management for Distributed Systems ║
|
|
8
|
+
* ║ ║
|
|
9
|
+
* ║ Project: wilfredwake ║
|
|
10
|
+
* ║ Version: 1.0.0 ║
|
|
11
|
+
* ║ License: MIT ║
|
|
12
|
+
* ║ ║
|
|
13
|
+
* ╚═══════════════════════════════════════════════════════════════╝
|
|
14
|
+
*
|
|
15
|
+
* PURPOSE
|
|
16
|
+
* ═══════════════════════════════════════════════════════════════
|
|
17
|
+
* wilfredwake is a CLI tool to manage sleeping development services
|
|
18
|
+
* in distributed systems, ensuring developers can wake services on
|
|
19
|
+
* demand while respecting dependency order and checking readiness.
|
|
20
|
+
*
|
|
21
|
+
* CORE FEATURES
|
|
22
|
+
* ═══════════════════════════════════════════════════════════════
|
|
23
|
+
* • Service status checking and health monitoring
|
|
24
|
+
* • On-demand service waking with dependency awareness
|
|
25
|
+
* • Multi-developer support with centralized orchestrator
|
|
26
|
+
* • Configuration-driven service registry (YAML/JSON)
|
|
27
|
+
* • Human-readable colored output
|
|
28
|
+
* • Timeout and error handling
|
|
29
|
+
* • Multi-environment support (dev, staging, prod)
|
|
30
|
+
*
|
|
31
|
+
* ARCHITECTURE
|
|
32
|
+
* ═══════════════════════════════════════════════════════════════
|
|
33
|
+
* Developer CLI → Orchestrator (always-on) → Services
|
|
34
|
+
*
|
|
35
|
+
* CLI: Local interface developers use (this package)
|
|
36
|
+
* Orchestrator: Backend service managing state and wake operations
|
|
37
|
+
* Services: Individual microservices with /health and /wake endpoints
|
|
38
|
+
*
|
|
39
|
+
* SYSTEM COMPONENTS
|
|
40
|
+
* ═══════════════════════════════════════════════════════════════
|
|
41
|
+
* src/
|
|
42
|
+
* ├── cli/ # CLI interface
|
|
43
|
+
* │ ├── commands/ # CLI command implementations
|
|
44
|
+
* │ │ ├── init.js # Configuration setup
|
|
45
|
+
* │ │ ├── status.js # Service status checking
|
|
46
|
+
* │ │ ├── wake.js # Service wake operations
|
|
47
|
+
* │ │ └── health.js # Health checks
|
|
48
|
+
* │ ├── config.js # Configuration management
|
|
49
|
+
* │ └── utils.js # CLI utilities
|
|
50
|
+
* ├── orchestrator/ # Backend orchestrator
|
|
51
|
+
* │ ├── server.js # Express.js API server
|
|
52
|
+
* │ ├── registry.js # Service registry loader
|
|
53
|
+
* │ ├── orchestrator.js # Wake orchestration logic
|
|
54
|
+
* │ └── handlers/ # API request handlers
|
|
55
|
+
* ├── shared/ # Shared modules
|
|
56
|
+
* │ ├── colors.js # Color schemes and formatting
|
|
57
|
+
* │ ├── logger.js # Logging utilities
|
|
58
|
+
* │ └── errors.js # Error definitions
|
|
59
|
+
* └── config/ # Configuration files
|
|
60
|
+
* └── services.yaml # Service registry
|
|
61
|
+
* ├── bin/ # Executable entry point
|
|
62
|
+
* │ └── cli.js # CLI executable
|
|
63
|
+
* ├── package.json # NPM package definition
|
|
64
|
+
* └── index.js # Main entry point
|
|
65
|
+
*
|
|
66
|
+
* USAGE EXAMPLES
|
|
67
|
+
* ═══════════════════════════════════════════════════════════════
|
|
68
|
+
*
|
|
69
|
+
* # Initialize configuration (first-time setup)
|
|
70
|
+
* $ wilfredwake init
|
|
71
|
+
*
|
|
72
|
+
* # Check status of all services
|
|
73
|
+
* $ wilfredwake status
|
|
74
|
+
*
|
|
75
|
+
* # Check specific service status
|
|
76
|
+
* $ wilfredwake status auth
|
|
77
|
+
*
|
|
78
|
+
* # Wake all services
|
|
79
|
+
* $ wilfredwake wake all
|
|
80
|
+
*
|
|
81
|
+
* # Wake specific service
|
|
82
|
+
* $ wilfredwake wake auth
|
|
83
|
+
*
|
|
84
|
+
* # Wake service group
|
|
85
|
+
* $ wilfredwake wake payments
|
|
86
|
+
*
|
|
87
|
+
* # Health check (no waking)
|
|
88
|
+
* $ wilfredwake health
|
|
89
|
+
*
|
|
90
|
+
* # Environment-specific operations
|
|
91
|
+
* $ wilfredwake wake all --env staging
|
|
92
|
+
*
|
|
93
|
+
* # JSON output format
|
|
94
|
+
* $ wilfredwake status --format json
|
|
95
|
+
*
|
|
96
|
+
* CONFIGURATION
|
|
97
|
+
* ═══════════════════════════════════════════════════════════════
|
|
98
|
+
* Configuration is stored in ~/.wilfredwake/config.json
|
|
99
|
+
*
|
|
100
|
+
* Default values:
|
|
101
|
+
* {
|
|
102
|
+
* "orchestratorUrl": "http://localhost:3000",
|
|
103
|
+
* "token": null,
|
|
104
|
+
* "environment": "dev",
|
|
105
|
+
* "preferences": {
|
|
106
|
+
* "outputFormat": "table",
|
|
107
|
+
* "verbose": false,
|
|
108
|
+
* "autoWait": true,
|
|
109
|
+
* "timeout": 300
|
|
110
|
+
* }
|
|
111
|
+
* }
|
|
112
|
+
*
|
|
113
|
+
* SERVICE REGISTRY
|
|
114
|
+
* ═══════════════════════════════════════════════════════════════
|
|
115
|
+
* Service registry (services.yaml) defines:
|
|
116
|
+
* • Service name, URL, and health/wake endpoints
|
|
117
|
+
* • Service dependencies (for dependency-aware waking)
|
|
118
|
+
* • Environment configurations (dev, staging, prod)
|
|
119
|
+
* • Service grouping for bulk operations
|
|
120
|
+
*
|
|
121
|
+
* Example service definition:
|
|
122
|
+
* services:
|
|
123
|
+
* dev:
|
|
124
|
+
* auth:
|
|
125
|
+
* url: https://auth-dev.onrender.com
|
|
126
|
+
* health: /health
|
|
127
|
+
* wake: /wake
|
|
128
|
+
* dependsOn: []
|
|
129
|
+
*
|
|
130
|
+
* payment-consumer:
|
|
131
|
+
* url: https://payment-consumer-dev.onrender.com
|
|
132
|
+
* health: /health
|
|
133
|
+
* wake: /wake
|
|
134
|
+
* dependsOn: [auth]
|
|
135
|
+
*
|
|
136
|
+
* ORCHESTRATOR API
|
|
137
|
+
* ═══════════════════════════════════════════════════════════════
|
|
138
|
+
* The orchestrator backend provides REST APIs:
|
|
139
|
+
*
|
|
140
|
+
* GET /health - Orchestrator health check
|
|
141
|
+
* GET /api/status - Get service status
|
|
142
|
+
* GET /api/health - Perform health checks
|
|
143
|
+
* POST /api/wake - Wake services
|
|
144
|
+
* GET /api/registry - View service registry
|
|
145
|
+
* POST /api/reload - Reload service registry
|
|
146
|
+
*
|
|
147
|
+
* MULTI-DEVELOPER SUPPORT
|
|
148
|
+
* ═══════════════════════════════════════════════════════════════
|
|
149
|
+
* • CLI uses per-user token to identify developer
|
|
150
|
+
* • Orchestrator is shared/always-on (single source of truth)
|
|
151
|
+
* • Multiple developers can wake services concurrently
|
|
152
|
+
* • State is centralized in orchestrator
|
|
153
|
+
*
|
|
154
|
+
* DEPENDENCY ORDERING
|
|
155
|
+
* ═══════════════════════════════════════════════════════════════
|
|
156
|
+
* Services are woken in dependency order using topological sort:
|
|
157
|
+
*
|
|
158
|
+
* Example dependency chain:
|
|
159
|
+
* auth (no deps) → payment-producer (depends on auth)
|
|
160
|
+
* → payment-consumer (depends on payment-producer)
|
|
161
|
+
*
|
|
162
|
+
* When waking "all":
|
|
163
|
+
* 1. auth wakes first
|
|
164
|
+
* 2. Once auth is ready, payment-producer wakes
|
|
165
|
+
* 3. Once payment-producer is ready, payment-consumer wakes
|
|
166
|
+
*
|
|
167
|
+
* HEALTH CHECKS
|
|
168
|
+
* ═══════════════════════════════════════════════════════════════
|
|
169
|
+
* • Health endpoint: GET {service-url}/health (configurable)
|
|
170
|
+
* • Wake endpoint: POST {service-url}/wake (configurable)
|
|
171
|
+
* • Status codes < 300: Service is ready
|
|
172
|
+
* • Status code 503: Service is sleeping
|
|
173
|
+
* • Status codes >= 400: Service has issues
|
|
174
|
+
* • Timeout: Service not responding
|
|
175
|
+
*
|
|
176
|
+
* ERROR HANDLING
|
|
177
|
+
* ═══════════════════════════════════════════════════════════════
|
|
178
|
+
* • Timeouts: Services that don't respond within timeout
|
|
179
|
+
* • Failed health checks: Services that fail health validation
|
|
180
|
+
* • Circular dependencies: Detected and reported
|
|
181
|
+
* • Connection errors: Clear error messages with guidance
|
|
182
|
+
* • Partial success: Some services wake, others fail
|
|
183
|
+
*
|
|
184
|
+
* ENVIRONMENT VARIABLES
|
|
185
|
+
* ═══════════════════════════════════════════════════════════════
|
|
186
|
+
* PORT - Orchestrator port (default: 3000)
|
|
187
|
+
* REGISTRY_FILE - Path to service registry (default: src/config/services.yaml)
|
|
188
|
+
* NODE_ENV - Environment (development, production)
|
|
189
|
+
* REQUIRE_AUTH - Require authentication tokens
|
|
190
|
+
*
|
|
191
|
+
* FUTURE ENHANCEMENTS
|
|
192
|
+
* ═══════════════════════════════════════════════════════════════
|
|
193
|
+
* • CLI auto-completion support
|
|
194
|
+
* • Hot reload of service registry
|
|
195
|
+
* • Web UI for orchestration overview
|
|
196
|
+
* • Scoped groups and service tagging
|
|
197
|
+
* • API-based dynamic service registration
|
|
198
|
+
* • Slack/email notifications for sleeping services
|
|
199
|
+
* • Service metrics and performance tracking
|
|
200
|
+
* • Automatic health monitoring and alerting
|
|
201
|
+
* • Service lifecycle management (pause, stop, restart)
|
|
202
|
+
* • Multi-user authentication and authorization
|
|
203
|
+
*
|
|
204
|
+
* LICENSE
|
|
205
|
+
* ═══════════════════════════════════════════════════════════════
|
|
206
|
+
* MIT License - See LICENSE file for details
|
|
207
|
+
*
|
|
208
|
+
* REFERENCES
|
|
209
|
+
* ═══════════════════════════════════════════════════════════════
|
|
210
|
+
* • Render sleeping service behavior
|
|
211
|
+
* • Kubernetes orchestration concepts
|
|
212
|
+
* • Terraform infrastructure as code patterns
|
|
213
|
+
* • DevOps tooling best practices
|
|
214
|
+
*
|
|
215
|
+
*/
|
|
216
|
+
|
|
217
|
+
// Entry point - exports CLI version and utilities for programmatic use
|
|
218
|
+
export { default as ConfigManager } from './src/cli/config.js';
|
|
219
|
+
export { Logger, utils } from './src/shared/logger.js';
|
|
220
|
+
export { colors, format } from './src/shared/colors.js';
|
|
221
|
+
export { ServiceRegistry } from './src/orchestrator/registry.js';
|
|
222
|
+
export { Orchestrator, ServiceState } from './src/orchestrator/orchestrator.js';
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wilfredwake",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI Tool for Multi-Developer Development Environment Wake & Status Management",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"wilfredwake": "./bin/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node bin/cli.js",
|
|
12
|
+
"dev": "node --experimental-watch bin/cli.js",
|
|
13
|
+
"orchestrator": "node src/orchestrator/server.js",
|
|
14
|
+
"orchestrator:dev": "node --experimental-watch src/orchestrator/server.js",
|
|
15
|
+
"test": "node --test tests/**/*.test.js"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"cli",
|
|
19
|
+
"service-management",
|
|
20
|
+
"orchestration",
|
|
21
|
+
"development",
|
|
22
|
+
"wake",
|
|
23
|
+
"status"
|
|
24
|
+
],
|
|
25
|
+
"author": "Wilfred Wake",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"chalk": "^5.3.0",
|
|
29
|
+
"commander": "^11.1.0",
|
|
30
|
+
"axios": "^1.6.0",
|
|
31
|
+
"js-yaml": "^4.1.0",
|
|
32
|
+
"dotenv": "^16.3.1",
|
|
33
|
+
"express": "^4.18.2"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18.0.0"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ╔═══════════════════════════════════════════════════════════════╗
|
|
3
|
+
* ║ HEALTH COMMAND - Check Service Health ║
|
|
4
|
+
* ║ Performs health checks without waking services ║
|
|
5
|
+
* ║ Useful for monitoring and diagnostics ║
|
|
6
|
+
* ╚═══════════════════════════════════════════════════════════════╝
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import axios from 'axios';
|
|
10
|
+
import ConfigManager from '../config.js';
|
|
11
|
+
import { Logger, utils } from '../../shared/logger.js';
|
|
12
|
+
import { colors, format } from '../../shared/colors.js';
|
|
13
|
+
import chalk from 'chalk';
|
|
14
|
+
|
|
15
|
+
const logger = new Logger();
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Check health status of services
|
|
19
|
+
* Does NOT wake services, only checks their current health
|
|
20
|
+
*
|
|
21
|
+
* @param {string} service - Optional service name to check
|
|
22
|
+
* @param {Object} options - Command options
|
|
23
|
+
* @param {string} options.env - Environment (dev, staging, prod)
|
|
24
|
+
*/
|
|
25
|
+
export async function healthCommand(service, options) {
|
|
26
|
+
try {
|
|
27
|
+
// ═══════════════════════════════════════════════════════════════
|
|
28
|
+
// LOAD CONFIGURATION
|
|
29
|
+
// ═══════════════════════════════════════════════════════════════
|
|
30
|
+
const configManager = new ConfigManager();
|
|
31
|
+
const config = await configManager.loadConfig();
|
|
32
|
+
|
|
33
|
+
const env = options.env || config.environment;
|
|
34
|
+
|
|
35
|
+
logger.section('Service Health Check');
|
|
36
|
+
|
|
37
|
+
// ═══════════════════════════════════════════════════════════════
|
|
38
|
+
// FETCH HEALTH FROM ORCHESTRATOR
|
|
39
|
+
// ═══════════════════════════════════════════════════════════════
|
|
40
|
+
let stopSpinner;
|
|
41
|
+
try {
|
|
42
|
+
stopSpinner = logger.spinner('Checking service health...');
|
|
43
|
+
|
|
44
|
+
const response = await axios.get(
|
|
45
|
+
`${config.orchestratorUrl}/api/health`,
|
|
46
|
+
{
|
|
47
|
+
params: {
|
|
48
|
+
environment: env,
|
|
49
|
+
service: service || undefined,
|
|
50
|
+
},
|
|
51
|
+
timeout: 15000,
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
stopSpinner();
|
|
56
|
+
console.log(''); // New line after spinner
|
|
57
|
+
|
|
58
|
+
const services = response.data.services || [];
|
|
59
|
+
const timestamp = response.data.timestamp || new Date().toISOString();
|
|
60
|
+
|
|
61
|
+
// ═══════════════════════════════════════════════════════════════
|
|
62
|
+
// DISPLAY HEALTH RESULTS
|
|
63
|
+
// ═══════════════════════════════════════════════════════════════
|
|
64
|
+
_displayHealthStatus(services, env, timestamp);
|
|
65
|
+
|
|
66
|
+
// ═══════════════════════════════════════════════════════════════
|
|
67
|
+
// HEALTH SUMMARY
|
|
68
|
+
// ═══════════════════════════════════════════════════════════════
|
|
69
|
+
_displayHealthSummary(services);
|
|
70
|
+
|
|
71
|
+
process.exit(0);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
stopSpinner?.();
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
} catch (error) {
|
|
77
|
+
logger.error(`Health check failed: ${error.message}`);
|
|
78
|
+
|
|
79
|
+
if (error.code === 'ECONNREFUSED') {
|
|
80
|
+
console.log(
|
|
81
|
+
chalk.yellowBright(
|
|
82
|
+
'\n⚠ Could not connect to orchestrator. Make sure it\'s running.'
|
|
83
|
+
)
|
|
84
|
+
);
|
|
85
|
+
console.log(chalk.dim('Run: wilfredwake init'));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Display detailed health status
|
|
94
|
+
* @private
|
|
95
|
+
* @param {Array} services - Services health data
|
|
96
|
+
* @param {string} environment - Environment name
|
|
97
|
+
* @param {string} timestamp - Check timestamp
|
|
98
|
+
*/
|
|
99
|
+
function _displayHealthStatus(services, environment, timestamp) {
|
|
100
|
+
if (services.length === 0) {
|
|
101
|
+
logger.info('No services found in registry.');
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.log(chalk.cyanBright.bold(`\n💓 Health Status (${environment.toUpperCase()})\n`));
|
|
106
|
+
console.log(chalk.gray(`Last checked: ${new Date(timestamp).toLocaleString()}\n`));
|
|
107
|
+
|
|
108
|
+
// ═══════════════════════════════════════════════════════════════
|
|
109
|
+
// DISPLAY EACH SERVICE'S HEALTH
|
|
110
|
+
// ═══════════════════════════════════════════════════════════════
|
|
111
|
+
services.forEach((service) => {
|
|
112
|
+
const statusEmoji = _getHealthEmoji(service.status);
|
|
113
|
+
const statusColor = colors.status[service.status] || colors.status.unknown;
|
|
114
|
+
|
|
115
|
+
// Service header
|
|
116
|
+
console.log(
|
|
117
|
+
`${statusEmoji} ${statusColor.bold(service.name)} ${chalk.gray(
|
|
118
|
+
`(${service.status})`
|
|
119
|
+
)}`
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// Service details
|
|
123
|
+
if (service.url) {
|
|
124
|
+
console.log(
|
|
125
|
+
chalk.dim(` URL: ${service.url}`)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (service.responseTime) {
|
|
130
|
+
const timeColor =
|
|
131
|
+
service.responseTime > 1000 ? chalk.yellow : chalk.green;
|
|
132
|
+
console.log(
|
|
133
|
+
chalk.dim(` Response time: ${timeColor(
|
|
134
|
+
`${service.responseTime}ms`
|
|
135
|
+
)}`)
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (service.lastWakeTime) {
|
|
140
|
+
const lastWake = new Date(service.lastWakeTime).toLocaleString();
|
|
141
|
+
console.log(chalk.dim(` Last woken: ${lastWake}`));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (service.lastChecked) {
|
|
145
|
+
const lastCheck = new Date(service.lastChecked).toLocaleTimeString();
|
|
146
|
+
console.log(chalk.dim(` Last checked: ${lastCheck}`));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (service.statusCode) {
|
|
150
|
+
const codeColor =
|
|
151
|
+
service.statusCode < 300 ? chalk.green :
|
|
152
|
+
service.statusCode < 400 ? chalk.yellow :
|
|
153
|
+
chalk.red;
|
|
154
|
+
console.log(
|
|
155
|
+
chalk.dim(` Status code: ${codeColor(service.statusCode)}`)
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (service.error) {
|
|
160
|
+
console.log(chalk.redBright(` Error: ${service.error}`));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (service.dependencies && service.dependencies.length > 0) {
|
|
164
|
+
console.log(
|
|
165
|
+
chalk.dim(` Dependencies: ${service.dependencies.join(', ')}`)
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
console.log(''); // Spacing
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Display health summary statistics
|
|
175
|
+
* @private
|
|
176
|
+
* @param {Array} services - Services health data
|
|
177
|
+
*/
|
|
178
|
+
function _displayHealthSummary(services) {
|
|
179
|
+
if (services.length === 0) return;
|
|
180
|
+
|
|
181
|
+
const stats = {
|
|
182
|
+
total: services.length,
|
|
183
|
+
live: services.filter(s => s.status === 'live').length,
|
|
184
|
+
waking: services.filter(s => s.status === 'waking').length,
|
|
185
|
+
dead: services.filter(s => s.status === 'dead').length,
|
|
186
|
+
failed: services.filter(s => s.status === 'failed').length,
|
|
187
|
+
unknown: services.filter(s => s.status === 'unknown').length,
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
console.log(chalk.magentaBright.bold('Summary'));
|
|
191
|
+
console.log(` Total services: ${stats.total}`);
|
|
192
|
+
console.log(` ${chalk.greenBright('✓')} Live: ${chalk.greenBright(
|
|
193
|
+
stats.live
|
|
194
|
+
)}`);
|
|
195
|
+
if (stats.waking > 0) {
|
|
196
|
+
console.log(` ${chalk.yellowBright('⟳')} Waking: ${chalk.yellowBright(
|
|
197
|
+
stats.waking
|
|
198
|
+
)}`);
|
|
199
|
+
}
|
|
200
|
+
if (stats.dead > 0) {
|
|
201
|
+
console.log(` ${chalk.gray('⚫')} Dead: ${chalk.gray(
|
|
202
|
+
stats.dead
|
|
203
|
+
)}`);
|
|
204
|
+
}
|
|
205
|
+
if (stats.failed > 0) {
|
|
206
|
+
console.log(` ${chalk.redBright('✗')} Failed: ${chalk.redBright(
|
|
207
|
+
stats.failed
|
|
208
|
+
)}`);
|
|
209
|
+
}
|
|
210
|
+
if (stats.unknown > 0) {
|
|
211
|
+
console.log(` ${chalk.magentaBright('?')} Unknown: ${chalk.magentaBright(
|
|
212
|
+
stats.unknown
|
|
213
|
+
)}`);
|
|
214
|
+
}
|
|
215
|
+
console.log('');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Get emoji for health status
|
|
220
|
+
* @private
|
|
221
|
+
* @param {string} status - Service status
|
|
222
|
+
* @returns {string} Emoji character
|
|
223
|
+
*/
|
|
224
|
+
function _getHealthEmoji(status) {
|
|
225
|
+
const emojis = {
|
|
226
|
+
live: '💚',
|
|
227
|
+
dead: '😴',
|
|
228
|
+
waking: '🌅',
|
|
229
|
+
failed: '❌',
|
|
230
|
+
unknown: '❓',
|
|
231
|
+
// Backward compatibility
|
|
232
|
+
ready: '💚',
|
|
233
|
+
sleeping: '😴',
|
|
234
|
+
pending: '⏳',
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
return emojis[status] || '❓';
|
|
238
|
+
}
|