diff --git a/src/Commands/PlugNPrayCommand.php b/src/Commands/PlugNPrayCommand.php new file mode 100644 index 0000000..b3b3fb0 --- /dev/null +++ b/src/Commands/PlugNPrayCommand.php @@ -0,0 +1,372 @@ +option('php'); + $image = $this->option('image'); + $force = $this->option('force'); + + $projectName = $this->option('name') + ?: strtolower(preg_replace('/[^a-zA-Z0-9]/', '-', basename($basePath))); + $projectName = trim(preg_replace('/--+/', '-', $projectName), '-'); + + $traefikHost = $this->option('host') ?: "{$projectName}.localhost"; + $dbName = $this->option('db') ?: str_replace('-', '_', $projectName); + $dbPassword = $this->option('db-pass'); + + $enableQueue = ! $this->option('no-queue'); + $enableScheduler = ! $this->option('no-scheduler'); + $enableHorizon = (bool) $this->option('horizon'); + $enableRedis = ! $this->option('no-redis'); + $enableMysql = ! $this->option('no-mysql'); + $enableWebsocket = (bool) $this->option('websocket'); + $websocketPort = $this->option('websocket-port'); + + if ($enableHorizon) { + $enableQueue = false; + } + + // Safety check + if (! $force && file_exists("{$basePath}/docker-compose.yml")) { + $this->error('docker-compose.yml already exists. Use --force to overwrite.'); + + return self::FAILURE; + } + + $this->info(''); + $this->info('=========================================='); + $this->info(' plug-n-pray 🙏'); + $this->info('=========================================='); + $this->table( + ['Setting', 'Value'], + [ + ['Project', $projectName], + ['PHP', $phpVersion], + ['Image', "{$image}:php{$phpVersion}"], + ['Traefik host', $traefikHost], + ['MySQL', $enableMysql ? "Yes ({$dbName})" : 'No'], + ['Redis', $enableRedis ? 'Yes' : 'No'], + ['Queue', $enableQueue ? 'Yes' : 'No'], + ['Scheduler', $enableScheduler ? 'Yes' : 'No'], + ['Horizon', $enableHorizon ? 'Yes' : 'No'], + ['WebSocket', $enableWebsocket ? "Yes (port {$websocketPort})" : 'No'], + ] + ); + + if (! $force && ! $this->confirm('Generate Docker files with these settings?', true)) { + $this->info('Aborted.'); + + return self::SUCCESS; + } + + // Create supervisor directory + if (! is_dir("{$basePath}/docker/supervisor")) { + mkdir("{$basePath}/docker/supervisor", 0755, true); + } + + // Generate docker-compose.yml + $compose = $this->generateCompose( + $projectName, + $phpVersion, + $image, + $traefikHost, + $dbName, + $dbPassword, + $enableQueue, + $enableScheduler, + $enableHorizon, + $enableRedis, + $enableMysql, + $enableWebsocket, + $websocketPort + ); + file_put_contents("{$basePath}/docker-compose.yml", $compose); + + // Generate .env.docker + $envDocker = $this->generateEnvDocker( + $traefikHost, + $dbName, + $dbPassword, + $enableRedis, + $enableMysql, + $enableWebsocket, + $websocketPort + ); + file_put_contents("{$basePath}/.env.docker", $envDocker); + + // Generate websocket supervisor config + if ($enableWebsocket) { + $wsConf = <<info(''); + $this->info('Files created:'); + $this->line(' docker-compose.yml'); + $this->line(' .env.docker'); + $this->line(' docker/supervisor/'); + if ($enableWebsocket) { + $this->line(' docker/supervisor/websocket.conf'); + } + $this->info(''); + $this->info('Next steps:'); + $this->line(" 1. Merge .env.docker into your .env"); + $this->line(" 2. Create the network (once): docker network create web"); + $this->line(" 3. Start: docker compose up -d"); + $this->line(" 4. Visit: http://{$traefikHost}"); + $this->info(''); + $this->info('Pray it works. 🙏'); + + return self::SUCCESS; + } + + private function generateCompose( + string $name, + string $php, + string $image, + string $host, + string $dbName, + string $dbPassword, + bool $queue, + bool $scheduler, + bool $horizon, + bool $redis, + bool $mysql, + bool $websocket = false, + string $websocketPort = '6001' + ): string { + $enableQueue = $queue ? 'true' : 'false'; + $enableScheduler = $scheduler ? 'true' : 'false'; + $enableHorizon = $horizon ? 'true' : 'false'; + + $yaml = <<app->runningInConsole()) { + $this->commands([ + PlugNPrayCommand::class, + ]); + } } }