Skip to content

Commit 45d4bc0

Browse files
Merge pull request #69 from robsontenorio/improve-installer
Installer: improve with validations
2 parents ab5c83c + 1e67c6f commit 45d4bc0

File tree

4 files changed

+272
-56
lines changed

4 files changed

+272
-56
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"require": {
2222
"illuminate/support": "~10",
2323
"blade-ui-kit/blade-heroicons": "^2.1",
24-
"jfcherng/php-diff": "^6.15"
24+
"jfcherng/php-diff": "^6.15",
25+
"laravel/prompts": "^0.1.11"
2526
},
2627
"require-dev": {
2728
"phpunit/phpunit": "^10.2",

composer.lock

Lines changed: 58 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Console/Commands/MaryInstallCommand.php

Lines changed: 177 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
namespace Mary\Console\Commands;
44

55
use Illuminate\Console\Command;
6+
use Illuminate\Support\Facades\File;
67
use Illuminate\Support\Facades\Process;
8+
use Illuminate\Support\Str;
9+
use function Laravel\Prompts\select;
710

811
class MaryInstallCommand extends Command
912
{
@@ -13,34 +16,189 @@ class MaryInstallCommand extends Command
1316

1417
public function handle()
1518
{
16-
$this->info("\n\n🔨 Installing Mary...\n\n");
19+
$this->info("🔨 Mary installer");
1720

18-
$directories = Process::tty()->run('mkdir -p app/Livewire && mkdir -p resources/views/components/layouts');
19-
$this->info($directories->output());
21+
$this->warn('
22+
It will set up:
23+
- Livewire
24+
- Tailwind + daisyUI
25+
- Default layout
26+
- Welcome component
27+
- Route to Welcome');
2028

21-
$livewire = Process::tty()->run('composer require livewire/livewire');
22-
$this->info($livewire->output());
29+
/**
30+
* Install Volt ?
31+
*/
32+
$shouldInstallVolt = $this->askForVolt();
2333

24-
$js = Process::tty()->run('yarn add -D tailwindcss daisyui@latest postcss autoprefixer && npx tailwindcss init -p');
25-
$this->info($js->output());
34+
/**
35+
* Yarn or Npm ?
36+
*/
37+
$packageManagerCommand = $this->askForPackageInstaller();
2638

27-
$layout = Process::tty()->run('cp '.__DIR__.'/../../../stubs/app.blade.php resources/views/components/layouts/');
28-
$this->info($layout->output());
39+
/**
40+
* Check for existing STARTER KIT packages
41+
*/
42+
$composerJson = File::get(base_path() . "/composer.json");
43+
$targets = ['breeze', 'jetstream', 'genesis'];
44+
$this->checkForExistingPackages($composerJson, $targets);
2945

30-
$css = Process::tty()->run('cp '.__DIR__.'/../../../stubs/app.css resources/css/');
31-
$this->info($css->output());
46+
/**
47+
* Check for existing JS packages
48+
*/
49+
$packageJson = File::get(base_path() . "/package.json");
50+
$targets = ['tailwindcss', 'daisyui'];
51+
$this->checkForExistingPackages($packageJson, $targets);
3252

33-
$tailwindConfig = Process::tty()->run('cp '.__DIR__.'/../../../stubs/tailwind.config.js .');
34-
$this->info($tailwindConfig->output());
53+
/**
54+
* Check for stubs
55+
*/
56+
$this->checkForStubs();
3557

36-
$welcome = Process::tty()->run('cp '.__DIR__.'/../../../stubs/Welcome.php app/Livewire/');
37-
$this->info($welcome->output());
58+
/**
59+
* Install Livewire
60+
*/
61+
$this->info("\nInstalling Livewire...\n");
3862

39-
$route = Process::tty()->run('cp '.__DIR__.'/../../../stubs/web.php routes/');
40-
$this->info($route->output());
63+
Process::run('composer require livewire/livewire', function (string $type, string $output) {
64+
echo $output;
65+
})->throw();
4166

42-
$this->info('🌟 Done!');
43-
$this->info("\n\n==> Run `yarn dev`\n\n");
67+
if ($shouldInstallVolt == 'Yes') {
68+
$this->info("\nInstalling Livewire Volt...\n");
4469

70+
Process::run('composer require livewire/volt', function (string $type, string $output) {
71+
echo $output;
72+
})->throw();
73+
}
74+
75+
/**
76+
* Install daisyUI + Tailwind
77+
*/
78+
$this->info("\nInstalling daisyUI + Tailwind...\n");
79+
80+
Process::run("$packageManagerCommand tailwindcss daisyui@latest postcss autoprefixer && npx tailwindcss init -p", function (string $type, string $output) {
81+
echo $output;
82+
})->throw();
83+
84+
/**
85+
* Copy all stubs
86+
*/
87+
$this->copyStubs();
88+
89+
$this->info("\n🌟 Done! Run `yarn dev or npm run dev`\n");
90+
}
91+
92+
/**
93+
* Check for existing packages
94+
*/
95+
public function checkForExistingPackages(string $content, array $targets): void
96+
{
97+
collect($targets)->each(function (string $target) use ($content) {
98+
if (Str::of($content)->contains($target)) {
99+
$this->error("Automatic install works only for brand-new Laravel projects.");
100+
$this->warn("Detected: " . $target);
101+
102+
exit;
103+
}
104+
});
105+
}
106+
107+
/**
108+
* Check for existing stubs
109+
*/
110+
public function checkForStubs(): void
111+
{
112+
collect([
113+
[
114+
'path' => 'resources/views/components/layouts',
115+
'name' => 'app.blade.php'
116+
],
117+
[
118+
'path' => 'app/Livewire/',
119+
'name' => 'Welcome.php',
120+
],
121+
[
122+
'path' => '',
123+
'name' => 'tailwind.config.js',
124+
]
125+
])->each(function (array $item) {
126+
$file = base_path() . '/' . $item['path'] . $item['name'];
127+
128+
if (File::exists($file)) {
129+
$this->error("Automatic install works only for brand-new Laravel projects.");
130+
$this->warn('Detected:' . $file);
131+
132+
exit;
133+
}
134+
});
135+
}
136+
137+
public function copyStubs(): void
138+
{
139+
$this->info("Copying stubs...\n");
140+
141+
Process::run('mkdir -p app/Livewire && mkdir -p resources/views/components/layouts', function (string $type, string $output) {
142+
echo $output;
143+
})->throw();
144+
145+
Process::run('cp ' . __DIR__ . '/../../../stubs/app.blade.php resources/views/components/layouts/', function (string $type, string $output) {
146+
echo $output;
147+
})->throw();
148+
149+
Process::run('cp ' . __DIR__ . '/../../../stubs/app.css resources/css/', function (string $type, string $output) {
150+
echo $output;
151+
})->throw();
152+
153+
Process::run('cp ' . __DIR__ . '/../../../stubs/tailwind.config.js .', function (string $type, string $output) {
154+
echo $output;
155+
})->throw();
156+
157+
Process::run('cp ' . __DIR__ . '/../../../stubs/Welcome.php app/Livewire/', function (string $type, string $output) {
158+
echo $output;
159+
})->throw();
160+
161+
Process::run('cp ' . __DIR__ . '/../../../stubs/web.php routes/', function (string $type, string $output) {
162+
echo $output;
163+
})->throw();
164+
}
165+
166+
public function askForPackageInstaller(): string
167+
{
168+
$yarn = Process::run('which yarn')->output();
169+
$npm = Process::run('which npm')->output();
170+
171+
$options = [];
172+
173+
if (Str::of($yarn)->isNotEmpty()) {
174+
$options = array_merge($options, ['yarn add -D' => 'yarn']);
175+
}
176+
177+
if (Str::of($npm)->isNotEmpty()) {
178+
$options = array_merge($options, ['npm install --dev' => 'npm',]);
179+
}
180+
181+
if (count($options) == 0) {
182+
$this->error("You need yarn or npm installed.");
183+
184+
exit;
185+
}
186+
187+
return select(
188+
label: 'Install with ...',
189+
options: $options
190+
);
191+
}
192+
193+
/**
194+
* Also install Volt?
195+
*/
196+
public function askForVolt(): string
197+
{
198+
return select(
199+
'Also install `livewire/volt` ?',
200+
['Yes', 'No'],
201+
hint: 'No matter what is your choice, it always installs `livewire/livewire`'
202+
);
45203
}
46204
}

stubs/app.blade.php

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,48 @@
33
<head>
44
<meta charset="utf-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6-
<title>{{ $title ?? config('app.name') }}</title>
6+
<title>{{ isset($title) ? $title.' - '.config('app.name') : config('app.name') }}</title>
77

88
@vite(['resources/css/app.css', 'resources/js/app.js'])
99
</head>
1010
<body class="min-h-screen font-sans antialiased">
11-
<x-main full-width>
12-
<x-slot:sidebar drawer="main-drawer" collapsible class="pt-3 bg-sky-800 text-white">
13-
14-
<!-- Hidden when collapsed -->
15-
<div class="hidden-when-collapsed ml-5 font-black text-4xl text-yellow-500">mary</div>
16-
17-
<!-- Display when collapsed -->
18-
<div class="display-when-collapsed ml-5 font-black text-4xl text-orange-500">m</div>
19-
20-
<!-- Custom `active menu item background color` -->
21-
<x-menu activate-by-route active-bg-color="bg-base-300/10">
22-
23-
<!-- User -->
24-
@if($user = auth()->user())
11+
<x-main full-width>
12+
<x-slot:sidebar drawer="main-drawer" collapsible class="pt-3 bg-sky-800 text-white">
13+
14+
{{-- Hidden when collapsed --}}
15+
<div class="hidden-when-collapsed ml-5 font-black text-4xl text-yellow-500">mary</div>
16+
17+
{{-- Display when collapsed --}}
18+
<div class="display-when-collapsed ml-5 font-black text-4xl text-orange-500">m</div>
19+
20+
{{-- Custom `active menu item background color` --}}
21+
<x-menu activate-by-route active-bg-color="bg-base-300/10">
22+
23+
{{-- User --}}
24+
@if($user = auth()->user())
2525
<x-list-item :item="$user" sub-value="username" no-separator no-hover class="!-mx-2 mt-2 mb-5 border-y border-y-sky-900">
26-
<x-slot:actions>
26+
<x-slot:actions>
2727
<div class="tooltip tooltip-left" data-tip="logoff">
28-
<x-button icon="o-power" class="btn-circle btn-ghost btn-xs" />
28+
<x-button icon="o-power" class="btn-circle btn-ghost btn-xs" />
2929
</div>
3030
</x-slot:actions>
31-
</x-list-item>
32-
@endif
33-
34-
<x-menu-item title="Home" icon="o-home" link="/" />
35-
<x-menu-item title="Yeah" icon="o-sparkles" link="####" />
36-
37-
<x-menu-sub title="Settings" icon="o-cog-6-tooth">
38-
<x-menu-item title="Wifi" icon="o-wifi" link="####" />
39-
<x-menu-item title="Archives" icon="o-archive-box" link="####" />
40-
</x-menu-sub>
41-
</x-menu>
42-
</x-slot:sidebar>
43-
44-
<!-- The `$slot` goes here -->
45-
<x-slot:content>
46-
{{ $slot }}
47-
</x-slot:content>
48-
</x-main>
31+
</x-list-item>
32+
@endif
33+
34+
<x-menu-item title="Home" icon="o-home" link="/" />
35+
<x-menu-item title="Yeah" icon="o-sparkles" link="####" />
36+
37+
<x-menu-sub title="Settings" icon="o-cog-6-tooth">
38+
<x-menu-item title="Wifi" icon="o-wifi" link="####" />
39+
<x-menu-item title="Archives" icon="o-archive-box" link="####" />
40+
</x-menu-sub>
41+
</x-menu>
42+
</x-slot:sidebar>
43+
44+
{{-- The `$slot` goes here --}}
45+
<x-slot:content>
46+
{{ $slot }}
47+
</x-slot:content>
48+
</x-main>
4949
</body>
5050
</html>

0 commit comments

Comments
 (0)