Files
michaelschiemer/scripts/dev/hot-reload-server.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

145 lines
3.6 KiB
PHP

<?php
/**
* Development Hot Reload Endpoint
* Bypasses full framework bootstrap to avoid deprecation warnings
*/
declare(strict_types=1);
// Disable deprecation warnings for this development endpoint
error_reporting(E_ALL & ~E_DEPRECATED);
// Set error reporting for debugging
ini_set('display_errors', 1);
error_reporting(E_ALL & ~E_DEPRECATED);
// Set up minimal autoloading
require_once __DIR__ . '/../vendor/autoload.php';
try {
// Minimal framework classes needed
use App\Framework\Filesystem\ValueObjects\FilePath;
use App\Framework\Filesystem\FileWatcher;
use App\Framework\DateTime\SystemTimer;
// Simple .env parsing for development check
function loadEnvVar(string $key, string $envFile = null): ?string {
$envFile ??= __DIR__ . '/../.env';
if (!file_exists($envFile)) {
return null;
}
$content = file_get_contents($envFile);
if (preg_match("/^{$key}\s*=\s*(.*)$/m", $content, $matches)) {
return trim($matches[1], " \t\n\r\0\x0B\"'");
}
return null;
}
// Only allow in development
$appDebug = loadEnvVar('APP_DEBUG');
if ($appDebug !== 'true') {
http_response_code(403);
exit('Hot Reload is only available in development mode');
}
// Set SSE headers
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no'); // Disable nginx buffering
// Create file watcher
$fileWatcher = new FileWatcher(
FilePath::create(__DIR__ . '/..'),
new SystemTimer()
);
// Watch patterns
$watchPatterns = [
'src/**/*.php',
'resources/views/**/*.php',
'resources/views/**/*.view.php',
'config/**/*.php',
];
$ignorePatterns = [
'vendor/**',
'var/**',
'storage/**',
'tests/**',
'public/**',
];
// Send initial connection event
echo "event: connected\n";
echo "data: " . json_encode([
'status' => 'connected',
'timestamp' => date('c'),
'message' => 'Hot Reload server started'
]) . "\n\n";
flush();
// Keep connection alive and watch for changes
$lastCheck = time();
while (connection_aborted() === 0) {
// Check for file changes every 500ms
$changes = $fileWatcher->watchOnce($watchPatterns, $ignorePatterns);
foreach ($changes as $change) {
$reloadType = determineReloadType($change);
echo "event: reload\n";
echo "data: " . json_encode([
'type' => $reloadType->value,
'file' => $change->getPath(),
'timestamp' => $change->getTimestamp()->format('c'),
'message' => 'File changed: ' . basename($change->getPath())
]) . "\n\n";
flush();
}
// Send heartbeat every 30 seconds
if (time() - $lastCheck >= 30) {
echo "event: heartbeat\n";
echo "data: " . json_encode([
'timestamp' => date('c'),
'message' => 'Connection alive'
]) . "\n\n";
flush();
$lastCheck = time();
}
// Small delay to prevent high CPU usage
usleep(500000); // 500ms
}
function determineReloadType(FileChangeEvent $event): ReloadType
{
$path = $event->getPath();
// PHP files need full page reload
if (str_ends_with($path, '.php')) {
return ReloadType::FULL;
}
// CSS files can use hot replacement
if (str_ends_with($path, '.css')) {
return ReloadType::CSS;
}
// JS modules can use HMR if supported
if (str_ends_with($path, '.js') || str_ends_with($path, '.ts')) {
return ReloadType::HMR;
}
// Templates need full reload
if (str_ends_with($path, '.view.php')) {
return ReloadType::FULL;
}
return ReloadType::FULL;
}