-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
be40536
commit 6f3d474
Showing
14 changed files
with
741 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/.idea | ||
/vendor | ||
composer.phar | ||
composer.lock | ||
phpunit.xml | ||
.phpunit.result.cache | ||
.DS_Store | ||
Thumbs.db |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
# renum | ||
# Paragon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"name": "kirschbaum-development/paragon", | ||
"description": "A Laravel package for generating enum-like objects in typescript based on PHP enum classes.", | ||
"keywords": [ | ||
"laravel", | ||
"actions", | ||
"events" | ||
], | ||
"homepage": "https://github.com/kirschbaum-development/paragon", | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "Brandon Ferens", | ||
"email": "brandon@kirschbaumdevelopment.com", | ||
"role": "Developer" | ||
} | ||
], | ||
"require": { | ||
"php": "^8.0" | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"Kirschbaum\\Paragon\\": "src/" | ||
} | ||
}, | ||
"config": { | ||
"sort-packages": true | ||
}, | ||
"minimum-stability": "dev", | ||
"prefer-stable": true, | ||
"extra": { | ||
"laravel": { | ||
"providers": [ | ||
"Kirschbaum\\Paragon\\ParagonServiceProvider" | ||
] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
|
||
return [ | ||
'enums' => [ | ||
'abstract-class' => 'Enum', | ||
|
||
'paths' => [ | ||
'php' => app_path(), | ||
'generated' => 'js/enums', | ||
'methods' => 'js/vendors/paragon/enums', | ||
], | ||
], | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?php | ||
|
||
namespace Kirschbaum\Paragon\Commands; | ||
|
||
use Illuminate\Console\Command; | ||
use Illuminate\Support\Collection; | ||
use Kirschbaum\Paragon\Concerns\DiscoverEnums; | ||
use Kirschbaum\Paragon\Generators\AbstractEnumGenerator; | ||
use Kirschbaum\Paragon\Generators\EnumGenerator; | ||
use Symfony\Component\Console\Attribute\AsCommand; | ||
|
||
#[AsCommand(name: 'paragon:generate-enums', description: 'Generate Typescript versions of existing PHP enums')] | ||
class GenerateEnumsCommand extends Command | ||
{ | ||
/** | ||
* Execute the console command. | ||
*/ | ||
public function handle(): int | ||
{ | ||
$generatedEnums = $this->enums() | ||
->map(function ($enum) { | ||
return EnumGenerator::generate($enum); | ||
}) | ||
->filter(); | ||
|
||
$this->components->info("{$generatedEnums->count()} enums have been (re)generated."); | ||
|
||
AbstractEnumGenerator::generate(); | ||
|
||
$this->components->info('Abstract enum class has been (re)generated.'); | ||
|
||
return self::SUCCESS; | ||
} | ||
|
||
/** | ||
* Gather all enum namespaces for searching. | ||
*/ | ||
protected function enums(): Collection | ||
{ | ||
return DiscoverEnums::within(config('paragon.enums.paths.php')) | ||
->values(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?php | ||
|
||
namespace Kirschbaum\Paragon\Commands; | ||
|
||
use Illuminate\Console\Command; | ||
use Illuminate\Console\GeneratorCommand; | ||
use Illuminate\Contracts\Filesystem\FileNotFoundException; | ||
use Kirschbaum\Paragon\Generators\AbstractEnumGenerator; | ||
use Symfony\Component\Console\Attribute\AsCommand; | ||
use Symfony\Component\Console\Input\InputArgument; | ||
|
||
use function Laravel\Prompts\text; | ||
|
||
#[AsCommand(name: 'paragon:enum-method', description: 'Create a new typescript enum method')] | ||
class MakeEnumMethodCommand extends GeneratorCommand | ||
{ | ||
/** | ||
* Get the stub file for the generator. | ||
*/ | ||
protected function getStub(): string | ||
{ | ||
return __DIR__ . '/../../stubs/method.stub'; | ||
} | ||
|
||
/** | ||
* Execute the console command. | ||
* | ||
* @throws FileNotFoundException | ||
*/ | ||
public function handle(): int | ||
{ | ||
parent::handle(); | ||
|
||
AbstractEnumGenerator::generate(); | ||
|
||
$this->components | ||
->info("Abstract enum class has been rebuilt to include new [{$this->argument('name')}] method."); | ||
|
||
return self::SUCCESS; | ||
} | ||
|
||
/** | ||
* Get the console command arguments. | ||
*/ | ||
protected function getArguments(): array | ||
{ | ||
return [ | ||
['name', InputArgument::REQUIRED, 'The name of the enum method'], | ||
]; | ||
} | ||
|
||
/** | ||
* Interact further with the user if they were prompted for missing arguments. | ||
*/ | ||
protected function promptForMissingArgumentsUsing(): array | ||
{ | ||
return [ | ||
'name' => fn () => text( | ||
label: 'What is the name of the new enum method?', | ||
placeholder: 'e.g. asOptions', | ||
), | ||
]; | ||
} | ||
|
||
/** | ||
* Build the file with the given name. | ||
* | ||
* @throws FileNotFoundException | ||
*/ | ||
protected function buildClass($name): string | ||
{ | ||
$stub = $this->files->get($this->getStub()); | ||
|
||
return str_replace('{{ Method }}', $this->argument('name'), $stub); | ||
} | ||
|
||
/** | ||
* Get the destination class path. | ||
*/ | ||
protected function getPath($name): string | ||
{ | ||
return resource_path(config('paragon.enums.paths.methods')) . DIRECTORY_SEPARATOR . $this->argument('name') . '.ts'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
|
||
namespace Kirschbaum\Paragon\Concerns; | ||
|
||
use Illuminate\Support\Collection; | ||
use Illuminate\Support\Str; | ||
use ReflectionClass; | ||
use ReflectionException; | ||
use SplFileInfo; | ||
use Symfony\Component\Finder\Finder; | ||
|
||
class DiscoverEnums | ||
{ | ||
/** | ||
* Get all the enums by searching the given directory. | ||
*/ | ||
public static function within(array|string $path): Collection | ||
{ | ||
return static::getEnums(Finder::create()->files()->in($path)); | ||
} | ||
|
||
/** | ||
* Filter the files down to only enums. | ||
*/ | ||
protected static function getEnums($files): Collection | ||
{ | ||
return collect($files) | ||
->mapWithKeys(function ($file) { | ||
try { | ||
$reflector = new ReflectionClass($enum = static::classFromFile($file)); | ||
} catch (ReflectionException) { | ||
return []; | ||
} | ||
|
||
return $reflector->isEnum() | ||
? [$enum => $enum] | ||
: []; | ||
}) | ||
->filter(); | ||
} | ||
|
||
/** | ||
* Extract the class name from the given file path. | ||
*/ | ||
protected static function classFromFile(SplFileInfo $file): string | ||
{ | ||
$class = trim(Str::replaceFirst(base_path(), '', $file->getRealPath()), DIRECTORY_SEPARATOR); | ||
|
||
return str_replace( | ||
[DIRECTORY_SEPARATOR, ucfirst(basename(app()->path())) . '\\'], | ||
['\\', app()->getNamespace()], | ||
ucfirst(Str::replaceLast('.php', '', $class)) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?php | ||
|
||
namespace Kirschbaum\Paragon\Concerns; | ||
|
||
use Attribute; | ||
|
||
#[Attribute(Attribute::TARGET_METHOD)] | ||
class IgnoreWhenGeneratingTypescript {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<?php | ||
|
||
namespace Kirschbaum\Paragon\Generators; | ||
|
||
use Illuminate\Contracts\Filesystem\Filesystem; | ||
use Illuminate\Support\Collection; | ||
use Illuminate\Support\Facades\Storage; | ||
use Symfony\Component\Finder\Exception\DirectoryNotFoundException; | ||
use Symfony\Component\Finder\Finder; | ||
|
||
class AbstractEnumGenerator | ||
{ | ||
protected Filesystem $files; | ||
|
||
public function __construct() | ||
{ | ||
$this->files = Storage::createLocalDriver([ | ||
'root' => resource_path(config('paragon.enums.paths.generated')), | ||
]); | ||
} | ||
|
||
public function __invoke(): void | ||
{ | ||
$this->files->put($this->path(), $this->contents()); | ||
} | ||
|
||
public static function generate() | ||
{ | ||
return (new self())(); | ||
} | ||
|
||
/** | ||
* Inject all prepared data into the stub. | ||
*/ | ||
protected function contents(): string | ||
{ | ||
$imports = $this->imports(); | ||
$suffix = $imports->count() ? PHP_EOL : ''; | ||
|
||
return str(file_get_contents($this->stubPath())) | ||
->replace('{{ Abstract }}', config('paragon.enums.abstract-class')) | ||
->replace('{{ Imports }}', "{$imports->join('')}{$suffix}") | ||
->replace('{{ Methods }}', "{$this->methods($imports->keys())}{$suffix}"); | ||
} | ||
|
||
/** | ||
* Get the path to the stubs. | ||
*/ | ||
public function stubPath(): string | ||
{ | ||
return __DIR__ . '/../../stubs/abstract-enum.stub'; | ||
} | ||
|
||
/** | ||
* Build out the actual enum case object including the name, value if needed, and any public methods. | ||
*/ | ||
protected function imports(): Collection | ||
{ | ||
try { | ||
$files = Finder::create() | ||
->files() | ||
->in(resource_path(config('paragon.enums.paths.methods'))); | ||
} catch (DirectoryNotFoundException) { | ||
return collect(); | ||
} | ||
|
||
return collect($files) | ||
->mapWithKeys(function ($file) { | ||
$abstractPath = config('paragon.enums.paths.generated'); | ||
$filePath = str($file->getPath()) | ||
->after(resource_path()) | ||
->ltrim('/') | ||
->explode('/'); | ||
|
||
$relativePath = collect(explode('/', $abstractPath)) | ||
->diff($filePath) | ||
->map(fn () => '..') | ||
->merge($filePath->diff(explode('/', $abstractPath))) | ||
->join('/'); | ||
|
||
$name = (string) str($file->getFileName())->before('.'); | ||
|
||
return [$name => "import {$name} from '{$relativePath}/{$file->getFilename()}';" . PHP_EOL]; | ||
}) | ||
->sort(); | ||
} | ||
|
||
/** | ||
* Build out the actual enum case object including the name, value if needed, and any public methods. | ||
*/ | ||
protected function methods(Collection $methods): string | ||
{ | ||
return $methods->map(fn ($method) => PHP_EOL . "Enum.{$method} = {$method};") | ||
->join(''); | ||
} | ||
|
||
/** | ||
* Path where the enum will be saved. | ||
*/ | ||
protected function path(): string | ||
{ | ||
return config('paragon.enums.abstract-class') . '.ts'; | ||
} | ||
} |
Oops, something went wrong.