myaidev-method 0.0.7 → 0.1.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.
Files changed (37) hide show
  1. package/.claude/CLAUDE.md +52 -0
  2. package/.claude/agents/content-writer.md +155 -0
  3. package/.claude/commands/myai-configure.md +44 -0
  4. package/.claude/commands/myai-content-writer.md +78 -0
  5. package/.claude/commands/myai-wordpress-publish.md +120 -0
  6. package/.claude/mcp/gutenberg-converter.js +447 -0
  7. package/.claude/mcp/mcp-config.json +101 -0
  8. package/.claude/mcp/wordpress-server-simple.js +182 -0
  9. package/.claude/mcp/wordpress-server.js +1277 -0
  10. package/.claude/settings.local.json +12 -0
  11. package/COOLIFY_DEPLOYMENT.md +750 -0
  12. package/README.md +6 -6
  13. package/WORDPRESS_ADMIN_SCRIPTS.md +474 -0
  14. package/bin/cli.js +17 -22
  15. package/dist/mcp/gutenberg-converter.js +447 -0
  16. package/dist/mcp/mcp-config.json +101 -0
  17. package/dist/mcp/wordpress-server-simple.js +182 -0
  18. package/dist/mcp/wordpress-server.js +1277 -0
  19. package/package.json +29 -5
  20. package/src/lib/coolify-utils.js +380 -0
  21. package/src/lib/report-synthesizer.js +504 -0
  22. package/src/lib/wordpress-admin-utils.js +703 -0
  23. package/src/mcp/health-check.js +190 -0
  24. package/src/mcp/mcp-launcher.js +237 -0
  25. package/src/scripts/coolify-deploy-app.js +287 -0
  26. package/src/scripts/coolify-list-resources.js +199 -0
  27. package/src/scripts/coolify-status.js +97 -0
  28. package/src/scripts/test-coolify-deploy.js +47 -0
  29. package/src/scripts/wordpress-comprehensive-report.js +325 -0
  30. package/src/scripts/wordpress-health-check.js +175 -0
  31. package/src/scripts/wordpress-performance-check.js +461 -0
  32. package/src/scripts/wordpress-security-scan.js +221 -0
  33. package/src/templates/claude/agents/coolify-deploy.md +563 -0
  34. package/src/templates/claude/agents/wordpress-admin.md +228 -271
  35. package/src/templates/claude/commands/myai-configure.md +10 -74
  36. package/src/templates/claude/commands/myai-coolify-deploy.md +172 -0
  37. package/src/templates/claude/commands/myai-wordpress-publish.md +16 -8
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MCP Server Health Check Script
5
+ * Validates MCP server configuration and connectivity
6
+ */
7
+
8
+ import { spawn } from 'child_process';
9
+ import { promises as fs } from 'fs';
10
+ import path from 'path';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
+
15
+ export default async function healthCheck() {
16
+ console.log('šŸ” MyAIDev Method MCP Server Health Check');
17
+ console.log('==========================================\n');
18
+
19
+ const checks = [];
20
+
21
+ // Check 1: Environment variables
22
+ console.log('šŸ“‹ Checking environment configuration...');
23
+ const envChecks = {
24
+ 'WORDPRESS_URL': process.env.WORDPRESS_URL,
25
+ 'WORDPRESS_USERNAME': process.env.WORDPRESS_USERNAME,
26
+ 'WORDPRESS_APP_PASSWORD': process.env.WORDPRESS_APP_PASSWORD
27
+ };
28
+
29
+ let envConfigured = true;
30
+ Object.entries(envChecks).forEach(([key, value]) => {
31
+ if (value) {
32
+ console.log(` āœ… ${key}: configured`);
33
+ } else {
34
+ console.log(` āŒ ${key}: missing`);
35
+ envConfigured = false;
36
+ }
37
+ });
38
+
39
+ checks.push({
40
+ name: 'Environment Configuration',
41
+ status: envConfigured ? 'passed' : 'failed'
42
+ });
43
+
44
+ // Check 2: MCP server files
45
+ console.log('\nšŸ“ Checking MCP server files...');
46
+ const mcpServerPath = path.resolve(__dirname, '../../.claude/mcp/wordpress-server.js');
47
+
48
+ try {
49
+ await fs.access(mcpServerPath);
50
+ console.log(' āœ… WordPress MCP server file exists');
51
+ checks.push({
52
+ name: 'MCP Server Files',
53
+ status: 'passed'
54
+ });
55
+ } catch (error) {
56
+ console.log(' āŒ WordPress MCP server file missing');
57
+ checks.push({
58
+ name: 'MCP Server Files',
59
+ status: 'failed'
60
+ });
61
+ }
62
+
63
+ // Check 3: Dependencies
64
+ console.log('\nšŸ“¦ Checking dependencies...');
65
+ const requiredDeps = [
66
+ { name: '@modelcontextprotocol/sdk', path: '@modelcontextprotocol/sdk/server/mcp.js' },
67
+ { name: 'node-fetch', path: 'node-fetch' },
68
+ { name: 'dotenv', path: 'dotenv' },
69
+ { name: 'zod', path: 'zod' }
70
+ ];
71
+
72
+ let depsInstalled = true;
73
+ for (const dep of requiredDeps) {
74
+ try {
75
+ await import(dep.path);
76
+ console.log(` āœ… ${dep.name}: installed`);
77
+ } catch (error) {
78
+ console.log(` āŒ ${dep.name}: missing or failed to import`);
79
+ depsInstalled = false;
80
+ }
81
+ }
82
+
83
+ checks.push({
84
+ name: 'Dependencies',
85
+ status: depsInstalled ? 'passed' : 'failed'
86
+ });
87
+
88
+ // Check 4: MCP server startup test
89
+ if (envConfigured && depsInstalled) {
90
+ console.log('\nšŸš€ Testing MCP server startup...');
91
+
92
+ try {
93
+ const startupTest = await testServerStartup(mcpServerPath);
94
+ console.log(` āœ… MCP server starts successfully`);
95
+ checks.push({
96
+ name: 'MCP Server Startup',
97
+ status: 'passed'
98
+ });
99
+ } catch (error) {
100
+ console.log(` āŒ MCP server startup failed: ${error.message}`);
101
+ checks.push({
102
+ name: 'MCP Server Startup',
103
+ status: 'failed'
104
+ });
105
+ }
106
+ } else {
107
+ console.log('\nā­ļø Skipping MCP server startup test (dependencies not met)');
108
+ checks.push({
109
+ name: 'MCP Server Startup',
110
+ status: 'skipped'
111
+ });
112
+ }
113
+
114
+ // Summary
115
+ console.log('\nšŸ“Š Health Check Summary:');
116
+ const passed = checks.filter(c => c.status === 'passed').length;
117
+ const failed = checks.filter(c => c.status === 'failed').length;
118
+ const skipped = checks.filter(c => c.status === 'skipped').length;
119
+
120
+ checks.forEach(check => {
121
+ const icon = check.status === 'passed' ? 'āœ…' :
122
+ check.status === 'failed' ? 'āŒ' : 'ā­ļø';
123
+ console.log(` ${icon} ${check.name}: ${check.status}`);
124
+ });
125
+
126
+ console.log(`\nResult: ${passed} passed, ${failed} failed, ${skipped} skipped`);
127
+
128
+ if (failed === 0) {
129
+ console.log('\nšŸŽ‰ All checks passed! MCP server is ready to use.');
130
+ console.log('\nšŸ’” Next steps:');
131
+ console.log(' • Run: npm run mcp:start');
132
+ console.log(' • Or use: /myai-wordpress-publish "your-file.md"');
133
+ } else {
134
+ console.log('\nāš ļø Some checks failed. Please address the issues above.');
135
+ console.log('\nšŸ’” Common solutions:');
136
+ console.log(' • Set environment variables: /myai-configure wordpress');
137
+ console.log(' • Install dependencies: npm install');
138
+ console.log(' • Check file permissions and paths');
139
+ }
140
+
141
+ return {
142
+ passed,
143
+ failed,
144
+ skipped,
145
+ checks,
146
+ overall: failed === 0 ? 'healthy' : 'unhealthy'
147
+ };
148
+ }
149
+
150
+ async function testServerStartup(serverPath) {
151
+ return new Promise((resolve, reject) => {
152
+ const serverProcess = spawn('node', [serverPath], {
153
+ stdio: ['pipe', 'pipe', 'pipe'],
154
+ env: process.env
155
+ });
156
+
157
+ let startupOutput = '';
158
+ const timeout = setTimeout(() => {
159
+ serverProcess.kill();
160
+ reject(new Error('Server startup timeout'));
161
+ }, 5000);
162
+
163
+ serverProcess.stderr.on('data', (data) => {
164
+ startupOutput += data.toString();
165
+ if (startupOutput.includes('Enhanced WordPress MCP Server') ||
166
+ startupOutput.includes('running')) {
167
+ clearTimeout(timeout);
168
+ serverProcess.kill();
169
+ resolve(true);
170
+ }
171
+ });
172
+
173
+ serverProcess.on('error', (error) => {
174
+ clearTimeout(timeout);
175
+ reject(error);
176
+ });
177
+
178
+ serverProcess.on('exit', (code) => {
179
+ clearTimeout(timeout);
180
+ if (code !== 0 && code !== null) {
181
+ reject(new Error(`Server exited with code ${code}`));
182
+ }
183
+ });
184
+ });
185
+ }
186
+
187
+ // Run if called directly
188
+ if (import.meta.url === `file://${process.argv[1]}`) {
189
+ healthCheck().catch(console.error);
190
+ }
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MCP Server Launcher Script
5
+ * Manages MCP server lifecycle with proper error handling and configuration
6
+ */
7
+
8
+ import { spawn } from 'child_process';
9
+ import { promises as fs } from 'fs';
10
+ import path from 'path';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
+
15
+ class MCPLauncher {
16
+ constructor() {
17
+ this.serverProcess = null;
18
+ this.serverPath = path.resolve(__dirname, '../../.claude/mcp/wordpress-server.js');
19
+ this.isShuttingDown = false;
20
+ }
21
+
22
+ log(message, level = 'info') {
23
+ const timestamp = new Date().toISOString();
24
+ const prefix = {
25
+ info: 'šŸ”§',
26
+ success: 'āœ…',
27
+ error: 'āŒ',
28
+ warn: 'āš ļø'
29
+ }[level] || 'ā„¹ļø';
30
+
31
+ console.log(`[${timestamp}] ${prefix} ${message}`);
32
+ }
33
+
34
+ async validateEnvironment() {
35
+ this.log('Validating environment configuration...');
36
+
37
+ const required = ['WORDPRESS_URL', 'WORDPRESS_USERNAME', 'WORDPRESS_APP_PASSWORD'];
38
+ const missing = required.filter(key => !process.env[key]);
39
+
40
+ if (missing.length > 0) {
41
+ throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
42
+ }
43
+
44
+ this.log('Environment validation passed', 'success');
45
+ }
46
+
47
+ async validateServerFile() {
48
+ this.log('Checking MCP server file...');
49
+
50
+ try {
51
+ await fs.access(this.serverPath);
52
+ this.log('MCP server file found', 'success');
53
+ } catch (error) {
54
+ throw new Error(`MCP server file not found: ${this.serverPath}`);
55
+ }
56
+ }
57
+
58
+ async startServer() {
59
+ if (this.serverProcess) {
60
+ this.log('Server is already running', 'warn');
61
+ return;
62
+ }
63
+
64
+ this.log('Starting Enhanced WordPress MCP Server...');
65
+
66
+ this.serverProcess = spawn('node', [this.serverPath], {
67
+ stdio: ['inherit', 'pipe', 'pipe'],
68
+ env: process.env
69
+ });
70
+
71
+ // Handle server output
72
+ this.serverProcess.stdout.on('data', (data) => {
73
+ const output = data.toString().trim();
74
+ if (output) {
75
+ console.log(`[SERVER] ${output}`);
76
+ }
77
+ });
78
+
79
+ this.serverProcess.stderr.on('data', (data) => {
80
+ const output = data.toString().trim();
81
+ if (output) {
82
+ if (output.includes('Enhanced WordPress MCP Server') && output.includes('running')) {
83
+ this.log('MCP Server started successfully', 'success');
84
+ this.log(`Server PID: ${this.serverProcess.pid}`);
85
+ this.log('MCP Server is ready to accept connections');
86
+ } else if (output.includes('ERROR') || output.includes('Error')) {
87
+ this.log(`Server error: ${output}`, 'error');
88
+ } else {
89
+ console.log(`[SERVER] ${output}`);
90
+ }
91
+ }
92
+ });
93
+
94
+ // Handle server exit
95
+ this.serverProcess.on('exit', (code, signal) => {
96
+ if (!this.isShuttingDown) {
97
+ if (code === 0) {
98
+ this.log('Server exited gracefully');
99
+ } else {
100
+ this.log(`Server exited with code ${code} (signal: ${signal})`, 'error');
101
+ }
102
+ }
103
+ this.serverProcess = null;
104
+ });
105
+
106
+ this.serverProcess.on('error', (error) => {
107
+ this.log(`Server startup error: ${error.message}`, 'error');
108
+ this.serverProcess = null;
109
+ });
110
+
111
+ // Setup graceful shutdown
112
+ this.setupShutdownHandlers();
113
+ }
114
+
115
+ setupShutdownHandlers() {
116
+ const shutdown = async (signal) => {
117
+ if (this.isShuttingDown) return;
118
+
119
+ this.isShuttingDown = true;
120
+ this.log(`Received ${signal}, shutting down gracefully...`);
121
+
122
+ if (this.serverProcess) {
123
+ this.log('Stopping MCP server...');
124
+ this.serverProcess.kill('SIGTERM');
125
+
126
+ // Force kill after 10 seconds
127
+ setTimeout(() => {
128
+ if (this.serverProcess) {
129
+ this.log('Force killing server...', 'warn');
130
+ this.serverProcess.kill('SIGKILL');
131
+ }
132
+ }, 10000);
133
+
134
+ // Wait for server to exit
135
+ await new Promise((resolve) => {
136
+ if (!this.serverProcess) {
137
+ resolve();
138
+ return;
139
+ }
140
+
141
+ this.serverProcess.on('exit', () => {
142
+ resolve();
143
+ });
144
+ });
145
+ }
146
+
147
+ this.log('Shutdown complete');
148
+ process.exit(0);
149
+ };
150
+
151
+ process.on('SIGINT', () => shutdown('SIGINT'));
152
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
153
+ process.on('SIGHUP', () => shutdown('SIGHUP'));
154
+ }
155
+
156
+ async launch() {
157
+ try {
158
+ this.log('šŸš€ MyAIDev Method MCP Server Launcher');
159
+ this.log('=====================================');
160
+
161
+ await this.validateEnvironment();
162
+ await this.validateServerFile();
163
+ await this.startServer();
164
+
165
+ // Keep the launcher running
166
+ this.log('Launcher is monitoring server...');
167
+
168
+ } catch (error) {
169
+ this.log(`Launch failed: ${error.message}`, 'error');
170
+ process.exit(1);
171
+ }
172
+ }
173
+
174
+ async status() {
175
+ this.log('MCP Server Status Check');
176
+ this.log('======================');
177
+
178
+ if (this.serverProcess) {
179
+ this.log(`Server is running (PID: ${this.serverProcess.pid})`, 'success');
180
+ this.log(`Server path: ${this.serverPath}`);
181
+ } else {
182
+ this.log('Server is not running', 'warn');
183
+ }
184
+
185
+ // Environment status
186
+ const envVars = ['WORDPRESS_URL', 'WORDPRESS_USERNAME', 'WORDPRESS_APP_PASSWORD'];
187
+ this.log('\nEnvironment variables:');
188
+ envVars.forEach(key => {
189
+ const status = process.env[key] ? 'āœ…' : 'āŒ';
190
+ const value = process.env[key] ? 'configured' : 'missing';
191
+ console.log(` ${status} ${key}: ${value}`);
192
+ });
193
+
194
+ return {
195
+ running: !!this.serverProcess,
196
+ pid: this.serverProcess?.pid,
197
+ serverPath: this.serverPath
198
+ };
199
+ }
200
+ }
201
+
202
+ // CLI interface
203
+ async function main() {
204
+ const launcher = new MCPLauncher();
205
+ const command = process.argv[2] || 'start';
206
+
207
+ switch (command) {
208
+ case 'start':
209
+ await launcher.launch();
210
+ break;
211
+
212
+ case 'status':
213
+ await launcher.status();
214
+ break;
215
+
216
+ case 'health':
217
+ const { default: healthCheck } = await import('./health-check.js');
218
+ await healthCheck();
219
+ break;
220
+
221
+ default:
222
+ console.log('Usage: node mcp-launcher.js [start|status|health]');
223
+ console.log('');
224
+ console.log('Commands:');
225
+ console.log(' start - Start the MCP server (default)');
226
+ console.log(' status - Show server status');
227
+ console.log(' health - Run health check');
228
+ process.exit(1);
229
+ }
230
+ }
231
+
232
+ export { MCPLauncher };
233
+
234
+ // Run if called directly
235
+ if (import.meta.url === `file://${process.argv[1]}`) {
236
+ main().catch(console.error);
237
+ }
@@ -0,0 +1,287 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Coolify Application Deployment Script
5
+ * Deploy applications to Coolify with full configuration support
6
+ */
7
+
8
+ import { CoolifyUtils } from '../lib/coolify-utils.js';
9
+
10
+ const args = process.argv.slice(2);
11
+
12
+ const options = {
13
+ name: null,
14
+ repo: null,
15
+ branch: 'main',
16
+ buildPack: 'nixpacks',
17
+ port: '3000',
18
+ domain: null,
19
+ serverUuid: null,
20
+ projectUuid: null,
21
+ envFile: null,
22
+ instant: false,
23
+ force: false,
24
+ wait: true,
25
+ json: args.includes('--json'),
26
+ verbose: args.includes('--verbose') || args.includes('-v')
27
+ };
28
+
29
+ // Parse arguments
30
+ for (let i = 0; i < args.length; i++) {
31
+ switch (args[i]) {
32
+ case '--name':
33
+ options.name = args[++i];
34
+ break;
35
+ case '--repo':
36
+ case '--repository':
37
+ options.repo = args[++i];
38
+ break;
39
+ case '--branch':
40
+ options.branch = args[++i];
41
+ break;
42
+ case '--build-pack':
43
+ options.buildPack = args[++i];
44
+ break;
45
+ case '--port':
46
+ options.port = args[++i];
47
+ break;
48
+ case '--domain':
49
+ options.domain = args[++i];
50
+ break;
51
+ case '--server-uuid':
52
+ options.serverUuid = args[++i];
53
+ break;
54
+ case '--project-uuid':
55
+ options.projectUuid = args[++i];
56
+ break;
57
+ case '--env-file':
58
+ options.envFile = args[++i];
59
+ break;
60
+ case '--instant':
61
+ options.instant = true;
62
+ break;
63
+ case '--force':
64
+ options.force = true;
65
+ break;
66
+ case '--no-wait':
67
+ options.wait = false;
68
+ break;
69
+ case '--help':
70
+ case '-h':
71
+ printHelp();
72
+ process.exit(0);
73
+ }
74
+ }
75
+
76
+ function printHelp() {
77
+ console.log(`
78
+ Coolify Application Deployment Script
79
+
80
+ Usage: coolify-deploy-app [options]
81
+
82
+ Required Options:
83
+ --name <name> Application name
84
+ --repo <url> Git repository URL
85
+ --project-uuid <uuid> Target project UUID
86
+ --server-uuid <uuid> Target server UUID
87
+
88
+ Optional Options:
89
+ --branch <name> Git branch (default: main)
90
+ --build-pack <type> Build pack: nixpacks, dockerfile, static (default: nixpacks)
91
+ --port <port> Application port (default: 3000)
92
+ --domain <domain> Domain name for the application
93
+ --env-file <path> Environment variables file
94
+ --instant Deploy instantly (skip queue)
95
+ --force Force rebuild
96
+ --no-wait Don't wait for deployment to complete
97
+ --verbose Show detailed progress
98
+ -v Alias for --verbose
99
+ --json Output in JSON format
100
+ --help Show this help
101
+ -h Alias for --help
102
+
103
+ Examples:
104
+ # Basic deployment
105
+ node src/scripts/coolify-deploy-app.js \\
106
+ --name "myapp" \\
107
+ --repo "https://github.com/user/myapp" \\
108
+ --project-uuid "zg44coscocg0sko8k0wgcgkw" \\
109
+ --server-uuid "vcscogc44gko4k880ww880kk"
110
+
111
+ # With custom domain and environment
112
+ node src/scripts/coolify-deploy-app.js \\
113
+ --name "api-prod" \\
114
+ --repo "https://github.com/user/api" \\
115
+ --branch "production" \\
116
+ --domain "api.example.com" \\
117
+ --env-file ".env.production" \\
118
+ --project-uuid "zg44coscocg0sko8k0wgcgkw" \\
119
+ --server-uuid "vcscogc44gko4k880ww880kk"
120
+
121
+ # Dockerfile-based deployment
122
+ node src/scripts/coolify-deploy-app.js \\
123
+ --name "docker-app" \\
124
+ --repo "https://github.com/user/docker-app" \\
125
+ --build-pack "dockerfile" \\
126
+ --port "8080" \\
127
+ --project-uuid "zg44coscocg0sko8k0wgcgkw" \\
128
+ --server-uuid "vcscogc44gko4k880ww880kk"
129
+ `);
130
+ }
131
+
132
+ async function deployApplication() {
133
+ try {
134
+ // Validate required options
135
+ if (!options.name || !options.repo || !options.projectUuid || !options.serverUuid) {
136
+ console.error('Error: Missing required options');
137
+ console.error('Required: --name, --repo, --project-uuid, --server-uuid');
138
+ console.error('Run with --help for usage information');
139
+ process.exit(1);
140
+ }
141
+
142
+ if (options.verbose) {
143
+ console.error('Initializing Coolify connection...');
144
+ }
145
+
146
+ const coolify = new CoolifyUtils();
147
+
148
+ // Verify connectivity
149
+ const healthy = await coolify.healthCheck();
150
+ if (!healthy) {
151
+ throw new Error('Coolify is not reachable');
152
+ }
153
+
154
+ if (options.verbose) {
155
+ console.error('āœ“ Coolify is reachable');
156
+ console.error(`Deploying application: ${options.name}`);
157
+ console.error(`Repository: ${options.repo}`);
158
+ console.error(`Branch: ${options.branch}`);
159
+ console.error(`Build pack: ${options.buildPack}`);
160
+ }
161
+
162
+ // Build application configuration (Coolify API format)
163
+ const appConfig = {
164
+ project_uuid: options.projectUuid,
165
+ server_uuid: options.serverUuid,
166
+ environment_name: 'production', // Required field
167
+ git_repository: options.repo,
168
+ git_branch: options.branch,
169
+ name: options.name,
170
+ description: `Deployed via myaidev-method on ${new Date().toISOString()}`,
171
+ build_pack: options.buildPack,
172
+ ports_exposes: options.port,
173
+ instant_deploy: options.instant,
174
+ domains: options.domain ? [options.domain] : []
175
+ };
176
+
177
+ // Load environment variables if specified
178
+ if (options.envFile) {
179
+ if (options.verbose) {
180
+ console.error(`Loading environment from: ${options.envFile}`);
181
+ }
182
+ // Environment variables would be loaded here
183
+ // For now, we'll skip this as it requires reading the file
184
+ }
185
+
186
+ if (options.verbose) {
187
+ console.error('Creating application in Coolify...');
188
+ }
189
+
190
+ // Create application
191
+ const app = await coolify.createApplication(appConfig);
192
+
193
+ if (options.verbose) {
194
+ console.error(`āœ“ Application created: ${app.uuid}`);
195
+ console.error('Starting deployment...');
196
+ }
197
+
198
+ // Deploy application
199
+ const deployment = await coolify.deployApplication(app.uuid, {
200
+ force: options.force,
201
+ instant: options.instant
202
+ });
203
+
204
+ if (options.verbose) {
205
+ console.error('āœ“ Deployment triggered');
206
+ }
207
+
208
+ let result = { success: true, status: 'deployed' };
209
+
210
+ // Wait for deployment to complete
211
+ if (options.wait) {
212
+ if (options.verbose) {
213
+ console.error('Waiting for deployment to complete...');
214
+ }
215
+
216
+ result = await coolify.waitForDeployment(app.uuid, {
217
+ maxAttempts: 120,
218
+ interval: 5000
219
+ });
220
+
221
+ if (options.verbose) {
222
+ if (result.success) {
223
+ console.error(`āœ“ Deployment completed successfully after ${result.attempts} checks`);
224
+ } else {
225
+ console.error(`āœ— Deployment failed with status: ${result.status}`);
226
+ }
227
+ }
228
+ }
229
+
230
+ // Get final application state
231
+ const finalApp = await coolify.getApplication(app.uuid);
232
+
233
+ // Prepare output
234
+ const output = {
235
+ success: result.success,
236
+ application: {
237
+ uuid: finalApp.uuid,
238
+ name: finalApp.name,
239
+ status: finalApp.status || 'unknown',
240
+ url: finalApp.fqdn || 'Not configured',
241
+ repository: options.repo,
242
+ branch: options.branch
243
+ },
244
+ deployment: {
245
+ status: result.status,
246
+ timestamp: new Date().toISOString()
247
+ }
248
+ };
249
+
250
+ if (options.json) {
251
+ console.log(JSON.stringify(output, null, 2));
252
+ } else {
253
+ console.log('\n' + '='.repeat(60));
254
+ console.log('Deployment Result');
255
+ console.log('='.repeat(60));
256
+ console.log(`Status: ${result.success ? 'āœ“ Success' : 'āœ— Failed'}`);
257
+ console.log(`Application: ${finalApp.name}`);
258
+ console.log(`UUID: ${finalApp.uuid}`);
259
+ console.log(`URL: ${finalApp.fqdn || 'Configure domain in Coolify'}`);
260
+ console.log(`Repository: ${options.repo}`);
261
+ console.log(`Branch: ${options.branch}`);
262
+ console.log('='.repeat(60));
263
+ }
264
+
265
+ process.exit(result.success ? 0 : 1);
266
+ } catch (error) {
267
+ if (options.json) {
268
+ console.log(JSON.stringify({
269
+ success: false,
270
+ error: error.message,
271
+ timestamp: new Date().toISOString()
272
+ }, null, 2));
273
+ } else {
274
+ console.error(`\nError: ${error.message}`);
275
+ if (options.verbose) {
276
+ console.error(`Stack: ${error.stack}`);
277
+ }
278
+ }
279
+ process.exit(1);
280
+ }
281
+ }
282
+
283
+ if (import.meta.url === `file://${process.argv[1]}`) {
284
+ deployApplication();
285
+ }
286
+
287
+ export { deployApplication };