Current File : /home/exataengenharia/public_html/vendor/laravel/jetstream/src/Console/InstallCommand.php |
<?php
namespace Laravel\Jetstream\Console;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;
use RuntimeException;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process;
class InstallCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'jetstream:install {stack : The development stack that should be installed (inertia,livewire)}
{--dark : Indicate that dark mode support should be installed}
{--teams : Indicates if team support should be installed}
{--api : Indicates if API support should be installed}
{--verification : Indicates if email verification support should be installed}
{--pest : Indicates if Pest should be installed}
{--ssr : Indicates if Inertia SSR support should be installed}
{--composer=global : Absolute path to the Composer binary which should be used to install packages}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Install the Jetstream components and resources';
/**
* Execute the console command.
*
* @return int|null
*/
public function handle()
{
if (! in_array($this->argument('stack'), ['inertia', 'livewire'])) {
$this->components->error('Invalid stack. Supported stacks are [inertia] and [livewire].');
return 1;
}
// Publish...
$this->callSilent('vendor:publish', ['--tag' => 'jetstream-config', '--force' => true]);
$this->callSilent('vendor:publish', ['--tag' => 'jetstream-migrations', '--force' => true]);
$this->callSilent('vendor:publish', ['--tag' => 'fortify-config', '--force' => true]);
$this->callSilent('vendor:publish', ['--tag' => 'fortify-support', '--force' => true]);
$this->callSilent('vendor:publish', ['--tag' => 'fortify-migrations', '--force' => true]);
// Storage...
$this->callSilent('storage:link');
// "Home" Route...
$this->replaceInFile('/home', '/dashboard', app_path('Providers/RouteServiceProvider.php'));
if (file_exists(resource_path('views/welcome.blade.php'))) {
$this->replaceInFile('/home', '/dashboard', resource_path('views/welcome.blade.php'));
$this->replaceInFile('Home', 'Dashboard', resource_path('views/welcome.blade.php'));
}
// Fortify Provider...
$this->installServiceProviderAfter('RouteServiceProvider', 'FortifyServiceProvider');
// Configure Session...
$this->configureSession();
// Configure API...
if ($this->option('api')) {
$this->replaceInFile('// Features::api(),', 'Features::api(),', config_path('jetstream.php'));
}
// Configure Email Verification...
if ($this->option('verification')) {
$this->replaceInFile('// Features::emailVerification(),', 'Features::emailVerification(),', config_path('fortify.php'));
}
// Install Stack...
if ($this->argument('stack') === 'livewire') {
if (! $this->installLivewireStack()) {
return 1;
}
} elseif ($this->argument('stack') === 'inertia') {
if (! $this->installInertiaStack()) {
return 1;
}
}
// Emails...
(new Filesystem)->ensureDirectoryExists(resource_path('views/emails'));
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/resources/views/emails', resource_path('views/emails'));
// Tests...
$stubs = $this->getTestStubsPath();
if ($this->option('pest')) {
$this->removeComposerDevPackages(['phpunit/phpunit']);
if (! $this->requireComposerDevPackages(['pestphp/pest:^2.0', 'pestphp/pest-plugin-laravel:^2.0'])) {
return 1;
}
copy($stubs.'/Pest.php', base_path('tests/Pest.php'));
copy($stubs.'/ExampleTest.php', base_path('tests/Feature/ExampleTest.php'));
copy($stubs.'/ExampleUnitTest.php', base_path('tests/Unit/ExampleTest.php'));
}
copy($stubs.'/AuthenticationTest.php', base_path('tests/Feature/AuthenticationTest.php'));
copy($stubs.'/EmailVerificationTest.php', base_path('tests/Feature/EmailVerificationTest.php'));
copy($stubs.'/PasswordConfirmationTest.php', base_path('tests/Feature/PasswordConfirmationTest.php'));
copy($stubs.'/PasswordResetTest.php', base_path('tests/Feature/PasswordResetTest.php'));
copy($stubs.'/RegistrationTest.php', base_path('tests/Feature/RegistrationTest.php'));
}
/**
* Configure the session driver for Jetstream.
*
* @return void
*/
protected function configureSession()
{
if (! class_exists('CreateSessionsTable')) {
try {
$this->call('session:table');
} catch (Exception $e) {
//
}
}
$this->replaceInFile("'SESSION_DRIVER', 'file'", "'SESSION_DRIVER', 'database'", config_path('session.php'));
$this->replaceInFile('SESSION_DRIVER=file', 'SESSION_DRIVER=database', base_path('.env'));
$this->replaceInFile('SESSION_DRIVER=file', 'SESSION_DRIVER=database', base_path('.env.example'));
}
/**
* Install the Livewire stack into the application.
*
* @return bool
*/
protected function installLivewireStack()
{
// Install Livewire...
if (! $this->requireComposerPackages('livewire/livewire:^2.11')) {
return false;
}
// Sanctum...
(new Process([$this->phpBinary(), 'artisan', 'vendor:publish', '--provider=Laravel\Sanctum\SanctumServiceProvider', '--force'], base_path()))
->setTimeout(null)
->run(function ($type, $output) {
$this->output->write($output);
});
// Update Configuration...
$this->replaceInFile('inertia', 'livewire', config_path('jetstream.php'));
// $this->replaceInFile("'guard' => 'web'", "'guard' => 'sanctum'", config_path('auth.php'));
// NPM Packages...
$this->updateNodePackages(function ($packages) {
return [
'@tailwindcss/forms' => '^0.5.2',
'@tailwindcss/typography' => '^0.5.0',
'alpinejs' => '^3.0.6',
'@alpinejs/focus' => '^3.10.5',
'autoprefixer' => '^10.4.7',
'postcss' => '^8.4.14',
'tailwindcss' => '^3.1.0',
] + $packages;
});
// Tailwind Configuration...
copy(__DIR__.'/../../stubs/livewire/tailwind.config.js', base_path('tailwind.config.js'));
copy(__DIR__.'/../../stubs/livewire/postcss.config.js', base_path('postcss.config.js'));
copy(__DIR__.'/../../stubs/livewire/vite.config.js', base_path('vite.config.js'));
// Directories...
(new Filesystem)->ensureDirectoryExists(app_path('Actions/Fortify'));
(new Filesystem)->ensureDirectoryExists(app_path('Actions/Jetstream'));
(new Filesystem)->ensureDirectoryExists(app_path('View/Components'));
(new Filesystem)->ensureDirectoryExists(resource_path('css'));
(new Filesystem)->ensureDirectoryExists(resource_path('markdown'));
(new Filesystem)->ensureDirectoryExists(resource_path('views/api'));
(new Filesystem)->ensureDirectoryExists(resource_path('views/auth'));
(new Filesystem)->ensureDirectoryExists(resource_path('views/components'));
(new Filesystem)->ensureDirectoryExists(resource_path('views/layouts'));
(new Filesystem)->ensureDirectoryExists(resource_path('views/profile'));
(new Filesystem)->deleteDirectory(resource_path('sass'));
// Terms Of Service / Privacy Policy...
copy(__DIR__.'/../../stubs/resources/markdown/terms.md', resource_path('markdown/terms.md'));
copy(__DIR__.'/../../stubs/resources/markdown/policy.md', resource_path('markdown/policy.md'));
// Service Providers...
copy(__DIR__.'/../../stubs/app/Providers/JetstreamServiceProvider.php', app_path('Providers/JetstreamServiceProvider.php'));
$this->installServiceProviderAfter('FortifyServiceProvider', 'JetstreamServiceProvider');
// Models...
copy(__DIR__.'/../../stubs/app/Models/User.php', app_path('Models/User.php'));
// Factories...
copy(__DIR__.'/../../database/factories/UserFactory.php', base_path('database/factories/UserFactory.php'));
// Actions...
copy(__DIR__.'/../../stubs/app/Actions/Fortify/CreateNewUser.php', app_path('Actions/Fortify/CreateNewUser.php'));
copy(__DIR__.'/../../stubs/app/Actions/Fortify/UpdateUserProfileInformation.php', app_path('Actions/Fortify/UpdateUserProfileInformation.php'));
copy(__DIR__.'/../../stubs/app/Actions/Jetstream/DeleteUser.php', app_path('Actions/Jetstream/DeleteUser.php'));
// Components...
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/livewire/resources/views/components', resource_path('views/components'));
// View Components...
copy(__DIR__.'/../../stubs/livewire/app/View/Components/AppLayout.php', app_path('View/Components/AppLayout.php'));
copy(__DIR__.'/../../stubs/livewire/app/View/Components/GuestLayout.php', app_path('View/Components/GuestLayout.php'));
// Layouts...
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/livewire/resources/views/layouts', resource_path('views/layouts'));
// Single Blade Views...
copy(__DIR__.'/../../stubs/livewire/resources/views/dashboard.blade.php', resource_path('views/dashboard.blade.php'));
copy(__DIR__.'/../../stubs/livewire/resources/views/navigation-menu.blade.php', resource_path('views/navigation-menu.blade.php'));
copy(__DIR__.'/../../stubs/livewire/resources/views/terms.blade.php', resource_path('views/terms.blade.php'));
copy(__DIR__.'/../../stubs/livewire/resources/views/policy.blade.php', resource_path('views/policy.blade.php'));
// Other Views...
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/livewire/resources/views/api', resource_path('views/api'));
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/livewire/resources/views/profile', resource_path('views/profile'));
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/livewire/resources/views/auth', resource_path('views/auth'));
// Routes...
$this->replaceInFile('auth:api', 'auth:sanctum', base_path('routes/api.php'));
if (! Str::contains(file_get_contents(base_path('routes/web.php')), "'/dashboard'")) {
(new Filesystem)->append(base_path('routes/web.php'), $this->livewireRouteDefinition());
}
// Assets...
copy(__DIR__.'/../../stubs/resources/css/app.css', resource_path('css/app.css'));
copy(__DIR__.'/../../stubs/livewire/resources/js/app.js', resource_path('js/app.js'));
// Tests...
$stubs = $this->getTestStubsPath();
copy($stubs.'/livewire/ApiTokenPermissionsTest.php', base_path('tests/Feature/ApiTokenPermissionsTest.php'));
copy($stubs.'/livewire/BrowserSessionsTest.php', base_path('tests/Feature/BrowserSessionsTest.php'));
copy($stubs.'/livewire/CreateApiTokenTest.php', base_path('tests/Feature/CreateApiTokenTest.php'));
copy($stubs.'/livewire/DeleteAccountTest.php', base_path('tests/Feature/DeleteAccountTest.php'));
copy($stubs.'/livewire/DeleteApiTokenTest.php', base_path('tests/Feature/DeleteApiTokenTest.php'));
copy($stubs.'/livewire/ProfileInformationTest.php', base_path('tests/Feature/ProfileInformationTest.php'));
copy($stubs.'/livewire/TwoFactorAuthenticationSettingsTest.php', base_path('tests/Feature/TwoFactorAuthenticationSettingsTest.php'));
copy($stubs.'/livewire/UpdatePasswordTest.php', base_path('tests/Feature/UpdatePasswordTest.php'));
// Teams...
if ($this->option('teams')) {
$this->installLivewireTeamStack();
}
if (! $this->option('dark')) {
$this->removeDarkClasses((new Finder)
->in(resource_path('views'))
->name('*.blade.php')
->filter(fn ($file) => $file->getPathname() !== resource_path('views/welcome.blade.php'))
);
}
if (file_exists(base_path('pnpm-lock.yaml'))) {
$this->runCommands(['pnpm install', 'pnpm run build']);
} elseif (file_exists(base_path('yarn.lock'))) {
$this->runCommands(['yarn install', 'yarn run build']);
} else {
$this->runCommands(['npm install', 'npm run build']);
}
$this->line('');
$this->components->info('Livewire scaffolding installed successfully.');
return true;
}
/**
* Install the Livewire team stack into the application.
*
* @return void
*/
protected function installLivewireTeamStack()
{
// Directories...
(new Filesystem)->ensureDirectoryExists(resource_path('views/teams'));
// Other Views...
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/livewire/resources/views/teams', resource_path('views/teams'));
// Tests...
$stubs = $this->getTestStubsPath();
copy($stubs.'/livewire/CreateTeamTest.php', base_path('tests/Feature/CreateTeamTest.php'));
copy($stubs.'/livewire/DeleteTeamTest.php', base_path('tests/Feature/DeleteTeamTest.php'));
copy($stubs.'/livewire/InviteTeamMemberTest.php', base_path('tests/Feature/InviteTeamMemberTest.php'));
copy($stubs.'/livewire/LeaveTeamTest.php', base_path('tests/Feature/LeaveTeamTest.php'));
copy($stubs.'/livewire/RemoveTeamMemberTest.php', base_path('tests/Feature/RemoveTeamMemberTest.php'));
copy($stubs.'/livewire/UpdateTeamMemberRoleTest.php', base_path('tests/Feature/UpdateTeamMemberRoleTest.php'));
copy($stubs.'/livewire/UpdateTeamNameTest.php', base_path('tests/Feature/UpdateTeamNameTest.php'));
$this->ensureApplicationIsTeamCompatible();
}
/**
* Get the route definition(s) that should be installed for Livewire.
*
* @return string
*/
protected function livewireRouteDefinition()
{
return <<<'EOF'
Route::middleware([
'auth:sanctum',
config('jetstream.auth_session'),
'verified'
])->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
});
EOF;
}
/**
* Install the Inertia stack into the application.
*
* @return bool
*/
protected function installInertiaStack()
{
// Install Inertia...
if (! $this->requireComposerPackages('inertiajs/inertia-laravel:^0.6.8', 'tightenco/ziggy:^1.0')) {
return false;
}
// Install NPM packages...
$this->updateNodePackages(function ($packages) {
return [
'@inertiajs/vue3' => '^1.0.0',
'@tailwindcss/forms' => '^0.5.2',
'@tailwindcss/typography' => '^0.5.2',
'@vitejs/plugin-vue' => '^4.0.0',
'autoprefixer' => '^10.4.7',
'postcss' => '^8.4.14',
'tailwindcss' => '^3.1.0',
'vue' => '^3.2.31',
] + $packages;
});
// Sanctum...
(new Process([$this->phpBinary(), 'artisan', 'vendor:publish', '--provider=Laravel\Sanctum\SanctumServiceProvider', '--force'], base_path()))
->setTimeout(null)
->run(function ($type, $output) {
$this->output->write($output);
});
// Tailwind Configuration...
copy(__DIR__.'/../../stubs/inertia/tailwind.config.js', base_path('tailwind.config.js'));
copy(__DIR__.'/../../stubs/inertia/postcss.config.js', base_path('postcss.config.js'));
copy(__DIR__.'/../../stubs/inertia/vite.config.js', base_path('vite.config.js'));
// jsconfig.json...
copy(__DIR__.'/../../stubs/inertia/jsconfig.json', base_path('jsconfig.json'));
// Directories...
(new Filesystem)->ensureDirectoryExists(app_path('Actions/Fortify'));
(new Filesystem)->ensureDirectoryExists(app_path('Actions/Jetstream'));
(new Filesystem)->ensureDirectoryExists(resource_path('css'));
(new Filesystem)->ensureDirectoryExists(resource_path('js/Components'));
(new Filesystem)->ensureDirectoryExists(resource_path('js/Layouts'));
(new Filesystem)->ensureDirectoryExists(resource_path('js/Pages'));
(new Filesystem)->ensureDirectoryExists(resource_path('js/Pages/API'));
(new Filesystem)->ensureDirectoryExists(resource_path('js/Pages/Auth'));
(new Filesystem)->ensureDirectoryExists(resource_path('js/Pages/Profile'));
(new Filesystem)->ensureDirectoryExists(resource_path('views'));
(new Filesystem)->ensureDirectoryExists(resource_path('markdown'));
(new Filesystem)->deleteDirectory(resource_path('sass'));
// Terms Of Service / Privacy Policy...
copy(__DIR__.'/../../stubs/resources/markdown/terms.md', resource_path('markdown/terms.md'));
copy(__DIR__.'/../../stubs/resources/markdown/policy.md', resource_path('markdown/policy.md'));
// Service Providers...
copy(__DIR__.'/../../stubs/app/Providers/JetstreamServiceProvider.php', app_path('Providers/JetstreamServiceProvider.php'));
$this->installServiceProviderAfter('FortifyServiceProvider', 'JetstreamServiceProvider');
// Middleware...
(new Process([$this->phpBinary(), 'artisan', 'inertia:middleware', 'HandleInertiaRequests', '--force'], base_path()))
->setTimeout(null)
->run(function ($type, $output) {
$this->output->write($output);
});
$this->installMiddlewareAfter('SubstituteBindings::class', '\App\Http\Middleware\HandleInertiaRequests::class');
$this->installMiddlewareAfter('\App\Http\Middleware\HandleInertiaRequests::class', '\Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets::class');
// Models...
copy(__DIR__.'/../../stubs/app/Models/User.php', app_path('Models/User.php'));
// Factories...
copy(__DIR__.'/../../database/factories/UserFactory.php', base_path('database/factories/UserFactory.php'));
// Actions...
copy(__DIR__.'/../../stubs/app/Actions/Fortify/CreateNewUser.php', app_path('Actions/Fortify/CreateNewUser.php'));
copy(__DIR__.'/../../stubs/app/Actions/Fortify/UpdateUserProfileInformation.php', app_path('Actions/Fortify/UpdateUserProfileInformation.php'));
copy(__DIR__.'/../../stubs/app/Actions/Jetstream/DeleteUser.php', app_path('Actions/Jetstream/DeleteUser.php'));
// Blade Views...
copy(__DIR__.'/../../stubs/inertia/resources/views/app.blade.php', resource_path('views/app.blade.php'));
if (file_exists(resource_path('views/welcome.blade.php'))) {
unlink(resource_path('views/welcome.blade.php'));
}
// Inertia Pages...
copy(__DIR__.'/../../stubs/inertia/resources/js/Pages/Dashboard.vue', resource_path('js/Pages/Dashboard.vue'));
copy(__DIR__.'/../../stubs/inertia/resources/js/Pages/PrivacyPolicy.vue', resource_path('js/Pages/PrivacyPolicy.vue'));
copy(__DIR__.'/../../stubs/inertia/resources/js/Pages/TermsOfService.vue', resource_path('js/Pages/TermsOfService.vue'));
copy(__DIR__.'/../../stubs/inertia/resources/js/Pages/Welcome.vue', resource_path('js/Pages/Welcome.vue'));
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/inertia/resources/js/Components', resource_path('js/Components'));
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/inertia/resources/js/Layouts', resource_path('js/Layouts'));
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/inertia/resources/js/Pages/API', resource_path('js/Pages/API'));
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/inertia/resources/js/Pages/Auth', resource_path('js/Pages/Auth'));
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/inertia/resources/js/Pages/Profile', resource_path('js/Pages/Profile'));
// Routes...
$this->replaceInFile('auth:api', 'auth:sanctum', base_path('routes/api.php'));
copy(__DIR__.'/../../stubs/inertia/routes/web.php', base_path('routes/web.php'));
// Assets...
copy(__DIR__.'/../../stubs/resources/css/app.css', resource_path('css/app.css'));
copy(__DIR__.'/../../stubs/inertia/resources/js/app.js', resource_path('js/app.js'));
// Flush node_modules...
// static::flushNodeModules();
// Tests...
$stubs = $this->getTestStubsPath();
copy($stubs.'/inertia/ApiTokenPermissionsTest.php', base_path('tests/Feature/ApiTokenPermissionsTest.php'));
copy($stubs.'/inertia/BrowserSessionsTest.php', base_path('tests/Feature/BrowserSessionsTest.php'));
copy($stubs.'/inertia/CreateApiTokenTest.php', base_path('tests/Feature/CreateApiTokenTest.php'));
copy($stubs.'/inertia/DeleteAccountTest.php', base_path('tests/Feature/DeleteAccountTest.php'));
copy($stubs.'/inertia/DeleteApiTokenTest.php', base_path('tests/Feature/DeleteApiTokenTest.php'));
copy($stubs.'/inertia/ProfileInformationTest.php', base_path('tests/Feature/ProfileInformationTest.php'));
copy($stubs.'/inertia/TwoFactorAuthenticationSettingsTest.php', base_path('tests/Feature/TwoFactorAuthenticationSettingsTest.php'));
copy($stubs.'/inertia/UpdatePasswordTest.php', base_path('tests/Feature/UpdatePasswordTest.php'));
// Teams...
if ($this->option('teams')) {
$this->installInertiaTeamStack();
}
if ($this->option('ssr')) {
$this->installInertiaSsrStack();
}
if (! $this->option('dark')) {
$this->removeDarkClasses((new Finder)
->in(resource_path('js'))
->name('*.vue')
->notPath('Pages/Welcome.vue')
);
}
if (file_exists(base_path('pnpm-lock.yaml'))) {
$this->runCommands(['pnpm install', 'pnpm run build']);
} elseif (file_exists(base_path('yarn.lock'))) {
$this->runCommands(['yarn install', 'yarn run build']);
} else {
$this->runCommands(['npm install', 'npm run build']);
}
$this->line('');
$this->components->info('Inertia scaffolding installed successfully.');
return true;
}
/**
* Install the Inertia team stack into the application.
*
* @return void
*/
protected function installInertiaTeamStack()
{
// Directories...
(new Filesystem)->ensureDirectoryExists(resource_path('js/Pages/Profile'));
// Pages...
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/inertia/resources/js/Pages/Teams', resource_path('js/Pages/Teams'));
// Tests...
$stubs = $this->getTestStubsPath();
copy($stubs.'/inertia/CreateTeamTest.php', base_path('tests/Feature/CreateTeamTest.php'));
copy($stubs.'/inertia/DeleteTeamTest.php', base_path('tests/Feature/DeleteTeamTest.php'));
copy($stubs.'/inertia/InviteTeamMemberTest.php', base_path('tests/Feature/InviteTeamMemberTest.php'));
copy($stubs.'/inertia/LeaveTeamTest.php', base_path('tests/Feature/LeaveTeamTest.php'));
copy($stubs.'/inertia/RemoveTeamMemberTest.php', base_path('tests/Feature/RemoveTeamMemberTest.php'));
copy($stubs.'/inertia/UpdateTeamMemberRoleTest.php', base_path('tests/Feature/UpdateTeamMemberRoleTest.php'));
copy($stubs.'/inertia/UpdateTeamNameTest.php', base_path('tests/Feature/UpdateTeamNameTest.php'));
$this->ensureApplicationIsTeamCompatible();
}
/**
* Ensure the installed user model is ready for team usage.
*
* @return void
*/
protected function ensureApplicationIsTeamCompatible()
{
// Publish Team Migrations...
$this->callSilent('vendor:publish', ['--tag' => 'jetstream-team-migrations', '--force' => true]);
// Configuration...
$this->replaceInFile('// Features::teams([\'invitations\' => true])', 'Features::teams([\'invitations\' => true])', config_path('jetstream.php'));
// Directories...
(new Filesystem)->ensureDirectoryExists(app_path('Actions/Jetstream'));
(new Filesystem)->ensureDirectoryExists(app_path('Events'));
(new Filesystem)->ensureDirectoryExists(app_path('Policies'));
// Service Providers...
copy(__DIR__.'/../../stubs/app/Providers/JetstreamWithTeamsServiceProvider.php', app_path('Providers/JetstreamServiceProvider.php'));
// Models...
copy(__DIR__.'/../../stubs/app/Models/Membership.php', app_path('Models/Membership.php'));
copy(__DIR__.'/../../stubs/app/Models/Team.php', app_path('Models/Team.php'));
copy(__DIR__.'/../../stubs/app/Models/TeamInvitation.php', app_path('Models/TeamInvitation.php'));
copy(__DIR__.'/../../stubs/app/Models/UserWithTeams.php', app_path('Models/User.php'));
// Actions...
copy(__DIR__.'/../../stubs/app/Actions/Jetstream/AddTeamMember.php', app_path('Actions/Jetstream/AddTeamMember.php'));
copy(__DIR__.'/../../stubs/app/Actions/Jetstream/CreateTeam.php', app_path('Actions/Jetstream/CreateTeam.php'));
copy(__DIR__.'/../../stubs/app/Actions/Jetstream/DeleteTeam.php', app_path('Actions/Jetstream/DeleteTeam.php'));
copy(__DIR__.'/../../stubs/app/Actions/Jetstream/DeleteUserWithTeams.php', app_path('Actions/Jetstream/DeleteUser.php'));
copy(__DIR__.'/../../stubs/app/Actions/Jetstream/InviteTeamMember.php', app_path('Actions/Jetstream/InviteTeamMember.php'));
copy(__DIR__.'/../../stubs/app/Actions/Jetstream/RemoveTeamMember.php', app_path('Actions/Jetstream/RemoveTeamMember.php'));
copy(__DIR__.'/../../stubs/app/Actions/Jetstream/UpdateTeamName.php', app_path('Actions/Jetstream/UpdateTeamName.php'));
copy(__DIR__.'/../../stubs/app/Actions/Fortify/CreateNewUserWithTeams.php', app_path('Actions/Fortify/CreateNewUser.php'));
// Policies...
(new Filesystem)->copyDirectory(__DIR__.'/../../stubs/app/Policies', app_path('Policies'));
// Factories...
copy(__DIR__.'/../../database/factories/UserFactory.php', base_path('database/factories/UserFactory.php'));
copy(__DIR__.'/../../database/factories/TeamFactory.php', base_path('database/factories/TeamFactory.php'));
}
/**
* Install the Inertia SSR stack into the application.
*
* @return void
*/
protected function installInertiaSsrStack()
{
$this->updateNodePackages(function ($packages) {
return [
'@vue/server-renderer' => '^3.2.31',
] + $packages;
});
copy(__DIR__.'/../../stubs/inertia/resources/js/ssr.js', resource_path('js/ssr.js'));
$this->replaceInFile("input: 'resources/js/app.js',", "input: 'resources/js/app.js',".PHP_EOL." ssr: 'resources/js/ssr.js',", base_path('vite.config.js'));
copy(__DIR__.'/../../stubs/inertia/app/Http/Middleware/HandleInertiaRequests.php', app_path('Http/Middleware/HandleInertiaRequests.php'));
$this->replaceInFile('vite build', 'vite build && vite build --ssr', base_path('package.json'));
$this->replaceInFile('/node_modules', '/bootstrap/ssr'.PHP_EOL.'/node_modules', base_path('.gitignore'));
}
/**
* Install the service provider in the application configuration file.
*
* @param string $after
* @param string $name
* @return void
*/
protected function installServiceProviderAfter($after, $name)
{
if (! Str::contains($appConfig = file_get_contents(config_path('app.php')), 'App\\Providers\\'.$name.'::class')) {
file_put_contents(config_path('app.php'), str_replace(
'App\\Providers\\'.$after.'::class,',
'App\\Providers\\'.$after.'::class,'.PHP_EOL.' App\\Providers\\'.$name.'::class,',
$appConfig
));
}
}
/**
* Install the middleware to a group in the application Http Kernel.
*
* @param string $after
* @param string $name
* @param string $group
* @return void
*/
protected function installMiddlewareAfter($after, $name, $group = 'web')
{
$httpKernel = file_get_contents(app_path('Http/Kernel.php'));
$middlewareGroups = Str::before(Str::after($httpKernel, '$middlewareGroups = ['), '];');
$middlewareGroup = Str::before(Str::after($middlewareGroups, "'$group' => ["), '],');
if (! Str::contains($middlewareGroup, $name)) {
$modifiedMiddlewareGroup = str_replace(
$after.',',
$after.','.PHP_EOL.' '.$name.',',
$middlewareGroup,
);
file_put_contents(app_path('Http/Kernel.php'), str_replace(
$middlewareGroups,
str_replace($middlewareGroup, $modifiedMiddlewareGroup, $middlewareGroups),
$httpKernel
));
}
}
/**
* Returns the path to the correct test stubs.
*
* @return string
*/
protected function getTestStubsPath()
{
return $this->option('pest')
? __DIR__.'/../../stubs/pest-tests'
: __DIR__.'/../../stubs/tests';
}
/**
* Installs the given Composer Packages into the application.
*
* @param mixed $packages
* @return bool
*/
protected function requireComposerPackages($packages)
{
$composer = $this->option('composer');
if ($composer !== 'global') {
$command = [$this->phpBinary(), $composer, 'require'];
}
$command = array_merge(
$command ?? ['composer', 'require'],
is_array($packages) ? $packages : func_get_args()
);
return ! (new Process($command, base_path(), ['COMPOSER_MEMORY_LIMIT' => '-1']))
->setTimeout(null)
->run(function ($type, $output) {
$this->output->write($output);
});
}
/**
* Removes the given Composer Packages as "dev" dependencies.
*
* @param mixed $packages
* @return bool
*/
protected function removeComposerDevPackages($packages)
{
$composer = $this->option('composer');
if ($composer !== 'global') {
$command = [$this->phpBinary(), $composer, 'remove', '--dev'];
}
$command = array_merge(
$command ?? ['composer', 'remove', '--dev'],
is_array($packages) ? $packages : func_get_args()
);
return (new Process($command, base_path(), ['COMPOSER_MEMORY_LIMIT' => '-1']))
->setTimeout(null)
->run(function ($type, $output) {
$this->output->write($output);
}) === 0;
}
/**
* Install the given Composer Packages as "dev" dependencies.
*
* @param mixed $packages
* @return bool
*/
protected function requireComposerDevPackages($packages)
{
$composer = $this->option('composer');
if ($composer !== 'global') {
$command = [$this->phpBinary(), $composer, 'require', '--dev'];
}
$command = array_merge(
$command ?? ['composer', 'require', '--dev'],
is_array($packages) ? $packages : func_get_args()
);
return (new Process($command, base_path(), ['COMPOSER_MEMORY_LIMIT' => '-1']))
->setTimeout(null)
->run(function ($type, $output) {
$this->output->write($output);
}) === 0;
}
/**
* Update the "package.json" file.
*
* @param callable $callback
* @param bool $dev
* @return void
*/
protected static function updateNodePackages(callable $callback, $dev = true)
{
if (! file_exists(base_path('package.json'))) {
return;
}
$configurationKey = $dev ? 'devDependencies' : 'dependencies';
$packages = json_decode(file_get_contents(base_path('package.json')), true);
$packages[$configurationKey] = $callback(
array_key_exists($configurationKey, $packages) ? $packages[$configurationKey] : [],
$configurationKey
);
ksort($packages[$configurationKey]);
file_put_contents(
base_path('package.json'),
json_encode($packages, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT).PHP_EOL
);
}
/**
* Delete the "node_modules" directory and remove the associated lock files.
*
* @return void
*/
protected static function flushNodeModules()
{
tap(new Filesystem, function ($files) {
$files->deleteDirectory(base_path('node_modules'));
$files->delete(base_path('pnpm-lock.yaml'));
$files->delete(base_path('yarn.lock'));
$files->delete(base_path('package-lock.json'));
});
}
/**
* Replace a given string within a given file.
*
* @param string $search
* @param string $replace
* @param string $path
* @return void
*/
protected function replaceInFile($search, $replace, $path)
{
file_put_contents($path, str_replace($search, $replace, file_get_contents($path)));
}
/**
* Remove Tailwind dark classes from the given files.
*
* @param \Symfony\Component\Finder\Finder $finder
* @return void
*/
protected function removeDarkClasses(Finder $finder)
{
foreach ($finder as $file) {
file_put_contents($file->getPathname(), preg_replace('/\sdark:[^\s"\']+/', '', $file->getContents()));
}
}
/**
* Get the path to the appropriate PHP binary.
*
* @return string
*/
protected function phpBinary()
{
return (new PhpExecutableFinder())->find(false) ?: 'php';
}
/**
* Run the given commands.
*
* @param array $commands
* @return void
*/
protected function runCommands($commands)
{
$process = Process::fromShellCommandline(implode(' && ', $commands), null, null, null, null);
if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) {
try {
$process->setTty(true);
} catch (RuntimeException $e) {
$this->output->writeln(' <bg=yellow;fg=black> WARN </> '.$e->getMessage().PHP_EOL);
}
}
$process->run(function ($type, $line) {
$this->output->write(' '.$line);
});
}
}