diff --git a/src/Illuminate/Foundation/Console/BroadcastingInstallCommand.php b/src/Illuminate/Foundation/Console/BroadcastingInstallCommand.php index b23689671d18..e5b6e6fecddf 100644 --- a/src/Illuminate/Foundation/Console/BroadcastingInstallCommand.php +++ b/src/Illuminate/Foundation/Console/BroadcastingInstallCommand.php @@ -54,25 +54,33 @@ public function handle() $this->uncommentChannelsRoutesFile(); $this->enableBroadcastServiceProvider(); - // Install bootstrapping... - if (! file_exists($echoScriptPath = $this->laravel->resourcePath('js/echo.js'))) { - if (! is_dir($directory = $this->laravel->resourcePath('js'))) { - mkdir($directory, 0755, true); - } - - copy(__DIR__.'/stubs/echo-js.stub', $echoScriptPath); - } + // We have a specific echo version for React and Vue with Typescript, + // so check if this app contains React or Vue with Typescript + if ($this->appContainsReactWithTypescript() || $this->appContainsVueWithTypescript()) { + // If this is a React/Vue app with typescript, inject the Echo configuration in the app.tsx or app.ts file + $this->injectEchoConfigurationInApp(); + } else { + // Standard JavaScript implementation + if (! file_exists($echoScriptPath = $this->laravel->resourcePath('js/echo.js'))) { + if (! is_dir($directory = $this->laravel->resourcePath('js'))) { + mkdir($directory, 0755, true); + } - if (file_exists($bootstrapScriptPath = $this->laravel->resourcePath('js/bootstrap.js'))) { - $bootstrapScript = file_get_contents( - $bootstrapScriptPath - ); + copy(__DIR__.'/stubs/echo-js.stub', $echoScriptPath); + } - if (! str_contains($bootstrapScript, './echo')) { - file_put_contents( - $bootstrapScriptPath, - trim($bootstrapScript.PHP_EOL.file_get_contents(__DIR__.'/stubs/echo-bootstrap-js.stub')).PHP_EOL, + // Only add the bootstrap import for the standard JS implementation + if (file_exists($bootstrapScriptPath = $this->laravel->resourcePath('js/bootstrap.js'))) { + $bootstrapScript = file_get_contents( + $bootstrapScriptPath ); + + if (! str_contains($bootstrapScript, './echo')) { + file_put_contents( + $bootstrapScriptPath, + trim($bootstrapScript.PHP_EOL.file_get_contents(__DIR__.'/stubs/echo-bootstrap-js.stub')).PHP_EOL, + ); + } } } @@ -81,6 +89,38 @@ public function handle() $this->installNodeDependencies(); } + /** + * Detect if the user is using React with TypeScript + * + * @return bool + */ + protected function appContainsReactWithTypescript(): bool + { + $packageJsonPath = $this->laravel->basePath('package.json'); + if (!file_exists($packageJsonPath)) { + return false; + } + $packageJson = json_decode(file_get_contents($packageJsonPath), true); + return isset($packageJson['dependencies']['react']) && + isset($packageJson['dependencies']['typescript']); + } + + /** + * Detect if the user is using Vue with TypeScript + * + * @return bool + */ + protected function appContainsVueWithTypescript(): bool + { + $packageJsonPath = $this->laravel->basePath('package.json'); + if (!file_exists($packageJsonPath)) { + return false; + } + $packageJson = json_decode(file_get_contents($packageJsonPath), true); + return isset($packageJson['dependencies']['vue']) && + isset($packageJson['dependencies']['typescript']); + } + /** * Uncomment the "channels" routes file in the application bootstrap file. * @@ -134,6 +174,70 @@ protected function enableBroadcastServiceProvider() } } + /** + * Inject Echo configuration into the application's main file. + * + * @return void + */ + protected function injectEchoConfigurationInApp() + { + // Detect which stack we are using and set appropriate configuration + if ($this->appContainsVueWithTypescript()) { + $filePath = resource_path('js/app.ts'); + $importPath = 'laravel-echo/vue'; + $fileExtension = 'ts'; + } else { + // Default to React + $filePath = resource_path('js/app.tsx'); + $importPath = 'laravel-echo/react'; + $fileExtension = 'tsx'; + } + + // Check if file exists + if (!file_exists($filePath)) { + $this->components->warn("Could not find {$filePath}. Echo configuration not added."); + return; + } + + $contents = file_get_contents($filePath); + + // Prepare Echo configuration code + $echoCode = <<components->info("Echo configuration added to app.{$fileExtension}."); + } + } else { + // Add the Echo configuration to the top of the file if no import statements are found + $newContents = $echoCode . "\n" . $contents; + file_put_contents($filePath, $newContents); + $this->components->info("Echo configuration added to the top of app.{$fileExtension}."); + } + } + + /** * Install Laravel Reverb into the application if desired. *