Skip to content

Commit

Permalink
feat: add initial install command
Browse files Browse the repository at this point in the history
  • Loading branch information
bensherred committed Aug 29, 2024
1 parent 69ef8ef commit 0053966
Show file tree
Hide file tree
Showing 57 changed files with 1,363 additions and 29 deletions.
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "red-explosion/fabricate",
"description": "Laravel scaffolding/starter kit for building new applications.",
"description": "An opionated yet flexible package for scaffolding new Laravel applications.",
"license": "MIT",
"homepage": "https://github.com/red-explosion/fabricate",
"type": "library",
Expand All @@ -16,12 +16,12 @@
}
],
"require": {
"php": "^8.2",
"illuminate/support": "^10.0|^11.0"
"php": "^8.3",
"illuminate/support": "^11.0"
},
"require-dev": {
"laravel/pint": "^1.10",
"orchestra/testbench": "^8.0|^9.0",
"orchestra/testbench": "^9.0",
"pestphp/pest": "^2.6",
"pestphp/pest-plugin-arch": "^2.1",
"phpstan/phpstan": "^1.10",
Expand Down
5 changes: 0 additions & 5 deletions config/fabricate.php

This file was deleted.

Empty file removed database/factories/.gitkeep
Empty file.
Empty file removed database/migrations/.gitkeep
Empty file.
10 changes: 2 additions & 8 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
parameters:
paths:
- src/

level: max

ignoreErrors:

excludePaths:

checkMissingIterableValueType: false
paths:
- src
Empty file removed resources/views/.gitkeep
Empty file.
22 changes: 22 additions & 0 deletions src/Actions/ReplaceInFileAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace RedExplosion\Fabricate\Actions;

use Illuminate\Filesystem\Filesystem;

class ReplaceInFileAction
{
public function __construct(
protected readonly Filesystem $filesystem,
) {
}

public function handle(string $search, string $replace, string $path): void
{
$contents = str_replace($search, $replace, $this->filesystem->get($path));

$this->filesystem->put($path, $contents);
}
}
28 changes: 28 additions & 0 deletions src/Actions/RequireComposerPackagesAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace RedExplosion\Fabricate\Actions;

use Symfony\Component\Process\Process;

class RequireComposerPackagesAction
{
/**
* @param array<int, string> $packages
* @param bool $asDev
* @return bool
*/
public function handle(array $packages, bool $asDev = false): bool
{
$command = array_merge(
['composer', 'require'],
$packages,
$asDev ? ['--dev'] : [],
);

return (new Process($command, base_path(), ['COMPOSER_MEMORY_LIMIT' => '-1']))
->setTimeout(null)
->run() === 0; // TODO: log the output
}
}
21 changes: 21 additions & 0 deletions src/Console/InstallCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace RedExplosion\Fabricate\Console;

use Illuminate\Console\Command;
use RedExplosion\Fabricate\Data\InstallData;
use RedExplosion\Fabricate\Install;

class InstallCommand extends Command
{
protected $signature = 'fabricate:install';

protected $description = 'Install the Fabricate scaffolding';

public function handle(Install $install): void
{
$install->process(new InstallData());
}
}
13 changes: 13 additions & 0 deletions src/Data/InstallData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace RedExplosion\Fabricate\Data;

class InstallData
{
public function __construct(
//
) {
}
}
30 changes: 18 additions & 12 deletions src/FabricateServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,33 @@

namespace RedExplosion\Fabricate;

use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;

class FabricateServiceProvider extends ServiceProvider
class FabricateServiceProvider extends ServiceProvider implements DeferrableProvider
{
public function register(): void
{
$this->mergeConfigFrom(
path: __DIR__ . '/../config/fabricate.php',
key: 'fabricate',
);
}

public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->publishes(
paths: [
__DIR__ . '/../config/fabricate.php' => config_path('fabricate.php'),
],
groups: 'fabricate-config',
);
if (! $this->app->runningInConsole()) {
return;
}

$this->commands([
Console\InstallCommand::class,
]);
}

/**
* @return array<int, class-string>
*/
public function provides(): array
{
return [
Console\InstallCommand::class,
];
}
}
34 changes: 34 additions & 0 deletions src/Install.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace RedExplosion\Fabricate;

use Illuminate\Pipeline\Pipeline;
use RedExplosion\Fabricate\Data\InstallData;

class Install extends Pipeline
{
public function process(InstallData $data): InstallData
{
return $this->send($data)

Check failure on line 14 in src/Install.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method RedExplosion\Fabricate\Install::process() should return RedExplosion\Fabricate\Data\InstallData but returns mixed.
->through([
Pipes\InstallComposerDependencies::class,
Pipes\InstallYarnDependencies::class,
Pipes\PublishStubs::class,
Pipes\RegisterComposerScripts::class,
Pipes\RunRefactorScript::class,
Pipes\RunLintScript::class,
Pipes\RegisterHelpersFile::class,
Pipes\FixLarastanErrors::class,
Pipes\ConfigureTestingDatabase::class,
Pipes\RemoveDefaultController::class,
Pipes\RemoveMigrationComments::class,
Pipes\RemoveDownMigrations::class,
Pipes\ConfigureEloquentModels::class,
Pipes\RunRefactorScript::class,
Pipes\RunLintScript::class,
])
->thenReturn();
}
}
70 changes: 70 additions & 0 deletions src/Pipes/ConfigureEloquentModels.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

namespace RedExplosion\Fabricate\Pipes;

use Closure;
use RedExplosion\Fabricate\Actions\ReplaceInFileAction;
use RedExplosion\Fabricate\Data\InstallData;

class ConfigureEloquentModels
{
public function __construct(
protected readonly ReplaceInFileAction $replaceInFile,
) {
}

public function handle(InstallData $data, Closure $next)

Check failure on line 18 in src/Pipes/ConfigureEloquentModels.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method RedExplosion\Fabricate\Pipes\ConfigureEloquentModels::handle() has no return type specified.
{
// todo: remove fillable from user model

$this->replaceInFile->handle(
<<<EOT
use Illuminate\Support\ServiceProvider;
EOT,
<<<EOT
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\ServiceProvider;
EOT,
base_path('app/Providers/AppServiceProvider.php'),
);

$this->replaceInFile->handle(
<<<EOT
public function boot(): void
{
}
EOT,
<<<EOT
public function boot(): void
{
Model::unguard();
Model::preventLazyLoading(! \$this->app->isProduction());
Model::preventSilentlyDiscardingAttributes();
Model::preventAccessingMissingAttributes();
if (\$this->app->isProduction()) {
Model::handleLazyLoadingViolationUsing(function (Model \$model, string \$relation): void {
\$class = \$model::class;
Log::warning("Attempted to lazy load [{\$relation}] on model [{\$class}].");
});
}
Relation::enforceMorphMap([
'user' => User::class,
]);
}
EOT,
base_path('app/Providers/AppServiceProvider.php'),
);

return $next($data);
}
}
41 changes: 41 additions & 0 deletions src/Pipes/ConfigureTestingDatabase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace RedExplosion\Fabricate\Pipes;

use Closure;
use Illuminate\Filesystem\Filesystem;
use RedExplosion\Fabricate\Actions\ReplaceInFileAction;
use RedExplosion\Fabricate\Data\InstallData;

class ConfigureTestingDatabase
{
public function __construct(
protected readonly Filesystem $filesystem,
protected readonly ReplaceInFileAction $replaceInFile,
) {
}

public function handle(InstallData $data, Closure $next)

Check failure on line 20 in src/Pipes/ConfigureTestingDatabase.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method RedExplosion\Fabricate\Pipes\ConfigureTestingDatabase::handle() has no return type specified.
{
$this->filesystem->move(
base_path('phpunit.xml'),
base_path('phpunit.xml.dist'),
);

$this->replaceInFile->handle(
<<<EOT
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
EOT,
<<<EOT
<env name="DB_DATABASE" value="testing"/>
EOT,
base_path('phpunit.xml.dist'),
);

return $next($data);
}
}

41 changes: 41 additions & 0 deletions src/Pipes/FixLarastanErrors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace RedExplosion\Fabricate\Pipes;

use Closure;
use Illuminate\Filesystem\Filesystem;
use RedExplosion\Fabricate\Actions\ReplaceInFileAction;
use RedExplosion\Fabricate\Data\InstallData;

class FixLarastanErrors
{
public function __construct(
protected readonly ReplaceInFileAction $replaceInFile,
) {
}

public function handle(InstallData $data, Closure $next)

Check failure on line 19 in src/Pipes/FixLarastanErrors.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method RedExplosion\Fabricate\Pipes\FixLarastanErrors::handle() has no return type specified.
{
$this->replaceInFile->handle(
'use Illuminate\Database\Eloquent\Factories\HasFactory;',
<<<EOT
use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
EOT,
app_path('Models/User.php'),
);

$this->replaceInFile->handle(
'use HasFactory;',
<<<EOT
/** @use HasFactory<UserFactory> */
use HasFactory;
EOT,
app_path('Models/User.php'),
);

return $next($data);
}
}
Loading

0 comments on commit 0053966

Please sign in to comment.