argument('mode'); // Normalize mode aliases $normalized = match (strtolower($mode)) { 'dev', 'development' => Rsx::MODE_DEVELOPMENT, 'debug' => Rsx::MODE_DEBUG, 'prod', 'production' => Rsx::MODE_PRODUCTION, default => null, }; if ($normalized === null) { $this->error("Invalid mode: {$mode}"); $this->line(''); $this->line('Valid modes:'); $this->line(' dev, development - Auto-rebuild, full debugging'); $this->line(' debug - Production optimizations with sourcemaps'); $this->line(' prod, production - Full optimization'); return 1; } // Check current mode (for display purposes only - always rebuild) $current_mode = $this->_get_current_env_mode(); if ($current_mode === $normalized) { $this->info("Rebuilding {$normalized} mode..."); } else { $this->info("Switching to {$normalized} mode..."); } $this->newLine(); // Step 1: Update .env file $this->line(' [1/3] Updating .env...'); $this->_update_env_mode($normalized); // Clear the cached mode so subsequent calls see the new value Rsx::clear_mode_cache(); // Step 2: Clear all caches $this->line(' [2/3] Clearing caches...'); // Clear Laravel caches by deleting files directly (avoids triggering Manifest::init) $this->_clear_laravel_caches(); // Clear RSX caches directly (avoids triggering Manifest::init via artisan boot) $this->_clear_rsx_caches(); // Step 3: Build appropriate assets $this->line(' [3/3] Building assets...'); if ($normalized === Rsx::MODE_DEVELOPMENT) { // In development, pre-warm the bundle cache // Explicitly pass RSX_MODE to ensure subprocess uses correct mode passthru("RSX_MODE={$normalized} php artisan rsx:bundle:compile", $exit_code); if ($exit_code !== 0) { $this->warn('Bundle compilation had warnings, but continuing...'); } } else { // In debug/production, run the production build // RSX_FORCE_BUILD allows manifest rebuild even in production mode // Explicitly pass RSX_MODE to ensure subprocess uses correct mode passthru("RSX_MODE={$normalized} RSX_FORCE_BUILD=1 php artisan rsx:prod:build", $exit_code); if ($exit_code !== 0) { $this->error('Production build failed'); return 1; } } $this->newLine(); $this->info("[OK] Switched to {$normalized} mode"); return 0; } /** * Get current RSX_MODE from .env file (not from env() which may be cached) */ private function _get_current_env_mode(): string { $env_path = base_path('.env'); if (!file_exists($env_path)) { return Rsx::MODE_DEVELOPMENT; } $contents = file_get_contents($env_path); if (preg_match('/^RSX_MODE=(.*)$/m', $contents, $matches)) { return trim($matches[1]); } return Rsx::MODE_DEVELOPMENT; } /** * Update RSX_MODE in .env file */ private function _update_env_mode(string $mode): void { $env_path = base_path('.env'); if (!file_exists($env_path)) { // Create .env with just RSX_MODE file_put_contents($env_path, "RSX_MODE={$mode}\n"); return; } $contents = file_get_contents($env_path); if (preg_match('/^RSX_MODE=.*$/m', $contents)) { // Replace existing RSX_MODE $contents = preg_replace('/^RSX_MODE=.*$/m', "RSX_MODE={$mode}", $contents); } else { // Add RSX_MODE after APP_DEBUG or APP_URL if they exist, otherwise at end if (preg_match('/^APP_DEBUG=.*$/m', $contents)) { $contents = preg_replace( '/^(APP_DEBUG=.*)$/m', "$1\nRSX_MODE={$mode}", $contents, 1 ); } elseif (preg_match('/^APP_URL=.*$/m', $contents)) { $contents = preg_replace( '/^(APP_URL=.*)$/m', "$1\nRSX_MODE={$mode}", $contents, 1 ); } else { // Append to end $contents = rtrim($contents) . "\nRSX_MODE={$mode}\n"; } } file_put_contents($env_path, $contents); } /** * Clear Laravel caches by deleting files directly * (Avoids running artisan commands which trigger Manifest::init) */ private function _clear_laravel_caches(): void { $bootstrap_cache = base_path('bootstrap/cache'); // Config cache $config_cache = "{$bootstrap_cache}/config.php"; if (file_exists($config_cache)) { unlink($config_cache); } // Route cache $route_cache = "{$bootstrap_cache}/routes-v7.php"; if (file_exists($route_cache)) { unlink($route_cache); } // Services cache $services_cache = "{$bootstrap_cache}/services.php"; if (file_exists($services_cache)) { unlink($services_cache); } // Packages cache $packages_cache = "{$bootstrap_cache}/packages.php"; if (file_exists($packages_cache)) { unlink($packages_cache); } // Compiled views $views_path = storage_path('framework/views'); if (is_dir($views_path)) { $files = glob("{$views_path}/*.php"); foreach ($files as $file) { unlink($file); } } } /** * Clear RSX caches by deleting directories directly * (Avoids running artisan commands which trigger Manifest::init) */ private function _clear_rsx_caches(): void { // Clear rsx-build directory $build_path = storage_path('rsx-build'); if (is_dir($build_path)) { $this->_clear_directory_contents($build_path); } // Clear rsx-tmp directory $tmp_path = storage_path('rsx-tmp'); if (is_dir($tmp_path)) { $this->_clear_directory_contents($tmp_path); } } /** * Recursively clear directory contents */ private function _clear_directory_contents(string $path): void { if (!is_dir($path)) { return; } $files = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST ); foreach ($files as $file) { if ($file->isDir()) { rmdir($file->getRealPath()); } else { unlink($file->getRealPath()); } } } }