diff --git a/config/boost.php b/config/boost.php index c97043d..f175ca2 100644 --- a/config/boost.php +++ b/config/boost.php @@ -3,6 +3,16 @@ declare(strict_types=1); return [ - 'project_purpose' => null, - 'browser_logs' => true, + + /* + |-------------------------------------------------------------------------- + | Boost Browser Logs Watcher Switch + |-------------------------------------------------------------------------- + | + | The following option may be used to enable or disable browser logs watcher + | functionality which simply provides a single and convenient way to + | enable or disable browser logs functionality in Boost. + */ + + 'browser_logs_watcher' => env('BOOST_BROWSER_LOGS_WATCHER', true), ]; diff --git a/pint.json b/pint.json index 8f3e9cc..331166c 100644 --- a/pint.json +++ b/pint.json @@ -111,7 +111,7 @@ "phpdoc_align": { "align": "left", "spacing": { - "param": 2 + "param": 1 } }, "phpdoc_indent": true, diff --git a/src/BoostServiceProvider.php b/src/BoostServiceProvider.php index 90b6e46..ce5e9fe 100644 --- a/src/BoostServiceProvider.php +++ b/src/BoostServiceProvider.php @@ -7,10 +7,10 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken; use Illuminate\Http\Request; use Illuminate\Routing\Router; -use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Route; use Illuminate\Support\ServiceProvider; +use Illuminate\View\Compilers\BladeCompiler; use Laravel\Boost\Mcp\Boost; use Laravel\Boost\Middleware\InjectBoost; use Laravel\Mcp\Server\Facades\Mcp; @@ -21,18 +21,21 @@ class BoostServiceProvider extends ServiceProvider public function register(): void { $this->mergeConfigFrom( - __DIR__.'/../config/boost.php', 'boost' + __DIR__.'/../config/boost.php', + 'boost' ); $this->app->singleton(Roster::class, function () { - $composerLockPath = base_path('composer.lock'); - $packageLockPath = base_path('package-lock.json'); + $lockFiles = [ + base_path('composer.lock'), + base_path('package-lock.json'), + base_path('bun.lockb'), + base_path('pnpm-lock.yaml'), + base_path('yarn.lock'), + ]; $cacheKey = 'boost.roster.scan'; - $lastModified = max( - file_exists($composerLockPath) ? filemtime($composerLockPath) : 0, - file_exists($packageLockPath) ? filemtime($packageLockPath) : 0 - ); + $lastModified = max(array_map(fn ($path) => file_exists($path) ? filemtime($path) : 0, $lockFiles)); $cached = cache()->get($cacheKey); if ($cached && isset($cached['timestamp']) && $cached['timestamp'] >= $lastModified) { @@ -62,7 +65,7 @@ public function boot(Router $router): void $this->registerCommands(); $this->registerRoutes(); $this->registerBrowserLogger(); - $this->registerBladeDirectives(); + $this->callAfterResolving('blade.compiler', fn (BladeCompiler $bladeCompiler) => $this->registerBladeDirectives($bladeCompiler)); $this->hookIntoResponses($router); } @@ -93,10 +96,17 @@ private function registerRoutes(): void /** @var \Illuminate\Log\Logger $logger */ $logger = Log::channel('browser'); - /** @var array{type: 'error'|'warn'|'info'|'log'|'table'|'window_error'|'uncaught_error'|'unhandled_rejection', timestamp: string, data: array, url:string, userAgent:string} $log */ + /** + * @var array{ + * type: 'error'|'warn'|'info'|'log'|'table'|'window_error'|'uncaught_error'|'unhandled_rejection', + * timestamp: string, + * data: array, + * url:string, + * userAgent:string + * } $log */ foreach ($logs as $log) { $logger->write( - level: $this->jsTypeToPsr3($log['type']), + level: $this->mapJsTypeToPsr3Level($log['type']), message: $this->buildLogMessageFromData($log['data']), context: [ 'url' => $log['url'], @@ -107,34 +117,30 @@ private function registerRoutes(): void } return response()->json(['status' => 'logged']); - })->name('boost.browser-logs')->withoutMiddleware(VerifyCsrfToken::class); + }) + ->name('boost.browser-logs') + ->withoutMiddleware(VerifyCsrfToken::class); } /** * Build a string message for the log based on various input types. Single dimensional, and multi: - * "data":[{"message":"Unhandled Promise Rejection","reason":{"name":"TypeError","message":"NetworkError when attempting to fetch resource.","stack":""}}] + * "data":[ + * {"message":"Unhandled Promise Rejection","reason":{"name":"TypeError","message":"NetworkError when attempting to fetch resource.","stack":""}}] * - * @param array $data + * @param array $data */ protected function buildLogMessageFromData(array $data): string { $messages = []; - foreach ($data as $key => $value) { - if (is_array($value)) { - $nestedMessage = $this->buildLogMessageFromData($value); - if ($nestedMessage !== '') { - $messages[] = $nestedMessage; - } - } elseif (is_string($value) || is_numeric($value)) { - $messages[] = (string) $value; - } elseif (is_bool($value)) { - $messages[] = $value ? 'true' : 'false'; - } elseif (is_null($value)) { - $messages[] = 'null'; - } elseif (is_object($value)) { - $messages[] = json_encode($value); - } + foreach ($data as $value) { + $messages[] = match (true) { + is_array($value) => $this->buildLogMessageFromData($value), + is_string($value), is_numeric($value) => (string) $value, + is_bool($value) => $value ? 'true' : 'false', + is_null($value) => 'null', + is_object($value) => json_encode($value), + }; } return implode(' ', $messages); @@ -142,23 +148,22 @@ protected function buildLogMessageFromData(array $data): string protected function registerBrowserLogger(): void { - // Register a custom log channel for browser logs - config(['logging.channels.browser' => [ - 'driver' => 'single', - 'path' => storage_path('logs/browser.log'), - 'level' => env('LOG_LEVEL', 'debug'), - 'days' => 14, - ]]); + config([ + 'logging.channels.browser' => [ + 'driver' => 'single', + 'path' => storage_path('logs/browser.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'days' => 14, + ], + ]); } - protected function registerBladeDirectives(): void + protected function registerBladeDirectives(BladeCompiler $bladeCompiler): void { - Blade::directive('boostJs', function () { - return ''; - }); + $bladeCompiler->directive('boostJs', fn () => ''); } - private function jsTypeToPsr3(string $type): string + private function mapJsTypeToPsr3Level(string $type): string { return match ($type) { 'warn' => 'warning', @@ -173,7 +178,7 @@ private function jsTypeToPsr3(string $type): string private function hookIntoResponses(Router $router): void { - if (config('boost.browser_logs', true) === false) { + if (! config('boost.browser_logs_watcher', true)) { return; } diff --git a/src/Concerns/MakesHttpRequests.php b/src/Concerns/MakesHttpRequests.php index 97d9968..8f9b246 100644 --- a/src/Concerns/MakesHttpRequests.php +++ b/src/Concerns/MakesHttpRequests.php @@ -30,7 +30,7 @@ public function get(string $url): Response } /** - * @param array $json + * @param array $json */ public function json(string $url, array $json): Response { diff --git a/src/Contracts/Ide.php b/src/Contracts/Ide.php index 431420b..2186d13 100644 --- a/src/Contracts/Ide.php +++ b/src/Contracts/Ide.php @@ -10,8 +10,8 @@ interface Ide // Things to note: supports relative (absolute path required)? global mcp only? Prefer local file, but if global only we have to add the project name to the server name /** - * @param array $args - * @param array $env + * @param array $args + * @param array $env */ public function installMcp(string $key, string $command, array $args = [], array $env = []): bool; } diff --git a/src/Install/Agents/FileMcpIde.php b/src/Install/Agents/FileMcpIde.php index 3217c39..5e73a32 100644 --- a/src/Install/Agents/FileMcpIde.php +++ b/src/Install/Agents/FileMcpIde.php @@ -16,8 +16,8 @@ public function mcpPath(): string } /** - * @param array $args - * @param array $env + * @param array $args + * @param array $env */ public function installMcp(string $key, string $command, array $args = [], array $env = []): bool { diff --git a/src/Install/Agents/ShellMcpIde.php b/src/Install/Agents/ShellMcpIde.php index 3da4ce9..6871541 100644 --- a/src/Install/Agents/ShellMcpIde.php +++ b/src/Install/Agents/ShellMcpIde.php @@ -12,8 +12,8 @@ abstract class ShellMcpIde implements Ide protected string $shellCommand = 'echo "{command} {args} {env}"'; /** - * @param array $args - * @param array $env + * @param array $args + * @param array $env */ public function installMcp(string $key, string $command, array $args = [], array $env = []): bool { diff --git a/src/Install/ApplicationDetector.php b/src/Install/ApplicationDetector.php index 48e45c2..b42e234 100644 --- a/src/Install/ApplicationDetector.php +++ b/src/Install/ApplicationDetector.php @@ -189,7 +189,7 @@ public function detectInProject(string $basePath): array /** * Check if an application is installed based on its configuration. * - * @param array> $config + * @param array> $config */ protected function isAppInstalled(array $config, string $platform): bool { @@ -219,7 +219,7 @@ protected function isAppInstalled(array $config, string $platform): bool /** * Check if an application is used in the current project. * - * @param array> $config + * @param array> $config */ protected function isAppUsedInProject(array $config, string $basePath): bool { @@ -297,7 +297,7 @@ protected function getPlatform(): string /** * Add custom detection configuration for an application. * - * @param array>> $config + * @param array>> $config */ public function addDetectionConfig(string $app, array $config, ?string $platform = null): void { @@ -314,7 +314,7 @@ public function addDetectionConfig(string $app, array $config, ?string $platform /** * Add custom project detection configuration for an application. * - * @param array> $config + * @param array> $config */ public function addProjectDetectionConfig(string $app, array $config): void { diff --git a/src/Install/Cli/DisplayHelper.php b/src/Install/Cli/DisplayHelper.php index 4004394..6dde87b 100644 --- a/src/Install/Cli/DisplayHelper.php +++ b/src/Install/Cli/DisplayHelper.php @@ -7,7 +7,7 @@ class DisplayHelper { /** - * @param array> $data + * @param array> $data */ public static function datatable(array $data, int $cols = 80): void { @@ -96,7 +96,7 @@ public static function datatable(array $data, int $cols = 80): void } /** - * @param array $items + * @param array $items */ public static function grid(array $items, int $cols = 80): void { diff --git a/src/Mcp/ToolExecutor.php b/src/Mcp/ToolExecutor.php index 9758b95..7c8533e 100644 --- a/src/Mcp/ToolExecutor.php +++ b/src/Mcp/ToolExecutor.php @@ -19,7 +19,7 @@ public function __construct() /** * Execute a tool with the given arguments. * - * @param array $arguments + * @param array $arguments */ public function execute(string $toolClass, array $arguments = []): ToolResult { @@ -37,7 +37,7 @@ public function execute(string $toolClass, array $arguments = []): ToolResult /** * Execute tool in a separate process for isolation. * - * @param array $arguments + * @param array $arguments */ protected function executeInProcess(string $toolClass, array $arguments): ToolResult { @@ -80,7 +80,7 @@ protected function executeInProcess(string $toolClass, array $arguments): ToolRe /** * Execute tool inline (current process). * - * @param array $arguments + * @param array $arguments */ protected function executeInline(string $toolClass, array $arguments): ToolResult { @@ -117,7 +117,7 @@ protected function getTimeout(): int /** * Reconstruct a ToolResult from JSON data. * - * @param array $data + * @param array $data */ protected function reconstructToolResult(array $data): ToolResult { diff --git a/src/Mcp/Tools/ApplicationInfo.php b/src/Mcp/Tools/ApplicationInfo.php index 8e2d118..13a386d 100644 --- a/src/Mcp/Tools/ApplicationInfo.php +++ b/src/Mcp/Tools/ApplicationInfo.php @@ -32,7 +32,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { diff --git a/src/Mcp/Tools/BrowserLogs.php b/src/Mcp/Tools/BrowserLogs.php index 4bd11be..423ec05 100644 --- a/src/Mcp/Tools/BrowserLogs.php +++ b/src/Mcp/Tools/BrowserLogs.php @@ -31,7 +31,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { diff --git a/src/Mcp/Tools/DatabaseConnections.php b/src/Mcp/Tools/DatabaseConnections.php index c88f81f..050e5c3 100644 --- a/src/Mcp/Tools/DatabaseConnections.php +++ b/src/Mcp/Tools/DatabaseConnections.php @@ -24,7 +24,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { diff --git a/src/Mcp/Tools/DatabaseQuery.php b/src/Mcp/Tools/DatabaseQuery.php index 58fca95..ff8c439 100644 --- a/src/Mcp/Tools/DatabaseQuery.php +++ b/src/Mcp/Tools/DatabaseQuery.php @@ -38,7 +38,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { diff --git a/src/Mcp/Tools/DatabaseSchema.php b/src/Mcp/Tools/DatabaseSchema.php index cb63b34..7a2834c 100644 --- a/src/Mcp/Tools/DatabaseSchema.php +++ b/src/Mcp/Tools/DatabaseSchema.php @@ -32,7 +32,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { diff --git a/src/Mcp/Tools/GetAbsoluteUrl.php b/src/Mcp/Tools/GetAbsoluteUrl.php index 9a4ec45..37b626c 100644 --- a/src/Mcp/Tools/GetAbsoluteUrl.php +++ b/src/Mcp/Tools/GetAbsoluteUrl.php @@ -31,7 +31,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { diff --git a/src/Mcp/Tools/GetConfig.php b/src/Mcp/Tools/GetConfig.php index f50a5e3..04eee15 100644 --- a/src/Mcp/Tools/GetConfig.php +++ b/src/Mcp/Tools/GetConfig.php @@ -27,7 +27,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { diff --git a/src/Mcp/Tools/LastError.php b/src/Mcp/Tools/LastError.php index ab82236..3751f08 100644 --- a/src/Mcp/Tools/LastError.php +++ b/src/Mcp/Tools/LastError.php @@ -53,7 +53,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { diff --git a/src/Mcp/Tools/ListArtisanCommands.php b/src/Mcp/Tools/ListArtisanCommands.php index a4dbff9..47a72a6 100644 --- a/src/Mcp/Tools/ListArtisanCommands.php +++ b/src/Mcp/Tools/ListArtisanCommands.php @@ -26,7 +26,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { diff --git a/src/Mcp/Tools/ListAvailableConfigKeys.php b/src/Mcp/Tools/ListAvailableConfigKeys.php index 17cda31..d8a532d 100644 --- a/src/Mcp/Tools/ListAvailableConfigKeys.php +++ b/src/Mcp/Tools/ListAvailableConfigKeys.php @@ -25,7 +25,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { @@ -39,7 +39,7 @@ public function handle(array $arguments): ToolResult /** * Flatten a multi-dimensional config array into dot notation keys. * - * @param array> $array + * @param array> $array * @return array */ private function flattenToDotNotation(array $array, string $prefix = ''): array diff --git a/src/Mcp/Tools/ListAvailableEnvVars.php b/src/Mcp/Tools/ListAvailableEnvVars.php index b621689..e4384a8 100644 --- a/src/Mcp/Tools/ListAvailableEnvVars.php +++ b/src/Mcp/Tools/ListAvailableEnvVars.php @@ -27,7 +27,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { diff --git a/src/Mcp/Tools/ListRoutes.php b/src/Mcp/Tools/ListRoutes.php index 9825c95..b2a82a7 100644 --- a/src/Mcp/Tools/ListRoutes.php +++ b/src/Mcp/Tools/ListRoutes.php @@ -37,7 +37,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { @@ -79,7 +79,7 @@ public function handle(array $arguments): ToolResult } /** - * @param array $options + * @param array $options */ private function artisan(string $command, array $options = []): string { diff --git a/src/Mcp/Tools/ReadLogEntries.php b/src/Mcp/Tools/ReadLogEntries.php index 6cbefaa..135bb55 100644 --- a/src/Mcp/Tools/ReadLogEntries.php +++ b/src/Mcp/Tools/ReadLogEntries.php @@ -30,7 +30,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult { diff --git a/src/Mcp/Tools/ReportFeedback.php b/src/Mcp/Tools/ReportFeedback.php index cedc5e9..38bc925 100644 --- a/src/Mcp/Tools/ReportFeedback.php +++ b/src/Mcp/Tools/ReportFeedback.php @@ -28,7 +28,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult|Generator { diff --git a/src/Mcp/Tools/SearchDocs.php b/src/Mcp/Tools/SearchDocs.php index e55a6c3..ac118fd 100644 --- a/src/Mcp/Tools/SearchDocs.php +++ b/src/Mcp/Tools/SearchDocs.php @@ -46,7 +46,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult|Generator { diff --git a/src/Mcp/Tools/Tinker.php b/src/Mcp/Tools/Tinker.php index 6a8aaf9..d9b34ea 100644 --- a/src/Mcp/Tools/Tinker.php +++ b/src/Mcp/Tools/Tinker.php @@ -32,7 +32,7 @@ public function schema(ToolInputSchema $schema): ToolInputSchema } /** - * @param array $arguments + * @param array $arguments */ public function handle(array $arguments): ToolResult {